mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
Remove the mblaze backend from llvm.
Approval in here http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-July/064169.html llvm-svn: 187145
This commit is contained in:
parent
f3982a902a
commit
32f9d6abe2
@ -79,7 +79,6 @@ set(LLVM_ALL_TARGETS
|
||||
CppBackend
|
||||
Hexagon
|
||||
Mips
|
||||
MBlaze
|
||||
MSP430
|
||||
NVPTX
|
||||
PowerPC
|
||||
|
@ -407,7 +407,6 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch],
|
||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
mblaze-*) llvm_cv_target_arch="MBlaze" ;;
|
||||
nvptx-*) llvm_cv_target_arch="NVPTX" ;;
|
||||
s390x-*) llvm_cv_target_arch="SystemZ" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
@ -442,7 +441,6 @@ case $host in
|
||||
xcore-*) host_arch="XCore" ;;
|
||||
msp430-*) host_arch="MSP430" ;;
|
||||
hexagon-*) host_arch="Hexagon" ;;
|
||||
mblaze-*) host_arch="MBlaze" ;;
|
||||
s390x-*) host_arch="SystemZ" ;;
|
||||
*) host_arch="Unknown" ;;
|
||||
esac
|
||||
@ -674,7 +672,6 @@ else
|
||||
XCore) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;;
|
||||
*) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
@ -824,7 +821,7 @@ if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
fi
|
||||
case "$enableval" in
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend MBlaze NVPTX Hexagon SystemZ R600" ;;
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600" ;;
|
||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||
case "$a_target" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -841,7 +838,6 @@ case "$enableval" in
|
||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;;
|
||||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
|
||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="R600 $TARGETS_TO_BUILD" ;;
|
||||
@ -853,7 +849,6 @@ case "$enableval" in
|
||||
AArch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;;
|
||||
ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;;
|
||||
Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
|
10
configure
vendored
10
configure
vendored
@ -4033,7 +4033,6 @@ else
|
||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
mblaze-*) llvm_cv_target_arch="MBlaze" ;;
|
||||
nvptx-*) llvm_cv_target_arch="NVPTX" ;;
|
||||
s390x-*) llvm_cv_target_arch="SystemZ" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
@ -4068,7 +4067,6 @@ case $host in
|
||||
xcore-*) host_arch="XCore" ;;
|
||||
msp430-*) host_arch="MSP430" ;;
|
||||
hexagon-*) host_arch="Hexagon" ;;
|
||||
mblaze-*) host_arch="MBlaze" ;;
|
||||
s390x-*) host_arch="SystemZ" ;;
|
||||
*) host_arch="Unknown" ;;
|
||||
esac
|
||||
@ -5424,8 +5422,6 @@ else
|
||||
MSP430) TARGET_HAS_JIT=0
|
||||
;;
|
||||
Hexagon) TARGET_HAS_JIT=0
|
||||
;;
|
||||
MBlaze) TARGET_HAS_JIT=0
|
||||
;;
|
||||
NVPTX) TARGET_HAS_JIT=0
|
||||
;;
|
||||
@ -5664,7 +5660,7 @@ if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
fi
|
||||
case "$enableval" in
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend MBlaze NVPTX Hexagon SystemZ R600" ;;
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600" ;;
|
||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||
case "$a_target" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -5681,7 +5677,6 @@ case "$enableval" in
|
||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;;
|
||||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
|
||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="R600 $TARGETS_TO_BUILD" ;;
|
||||
@ -5693,7 +5688,6 @@ case "$enableval" in
|
||||
AArch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;;
|
||||
ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;;
|
||||
Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
@ -10551,7 +10545,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 10554 "configure"
|
||||
#line 10548 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
|
@ -1788,7 +1788,6 @@ Here is the table:
|
||||
:raw-html:`<th>Feature</th>`
|
||||
:raw-html:`<th>ARM</th>`
|
||||
:raw-html:`<th>Hexagon</th>`
|
||||
:raw-html:`<th>MBlaze</th>`
|
||||
:raw-html:`<th>MSP430</th>`
|
||||
:raw-html:`<th>Mips</th>`
|
||||
:raw-html:`<th>NVPTX</th>`
|
||||
@ -1803,7 +1802,6 @@ Here is the table:
|
||||
:raw-html:`<td><a href="#feat_reliable">is generally reliable</a></td>`
|
||||
:raw-html:`<td class="yes"></td> <!-- ARM -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- Hexagon -->`
|
||||
:raw-html:`<td class="no"></td> <!-- MBlaze -->`
|
||||
:raw-html:`<td class="unknown"></td> <!-- MSP430 -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- Mips -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- NVPTX -->`
|
||||
@ -1818,7 +1816,6 @@ Here is the table:
|
||||
:raw-html:`<td><a href="#feat_asmparser">assembly parser</a></td>`
|
||||
:raw-html:`<td class="no"></td> <!-- ARM -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Hexagon -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- MBlaze -->`
|
||||
:raw-html:`<td class="no"></td> <!-- MSP430 -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Mips -->`
|
||||
:raw-html:`<td class="no"></td> <!-- NVPTX -->`
|
||||
@ -1833,7 +1830,6 @@ Here is the table:
|
||||
:raw-html:`<td><a href="#feat_disassembler">disassembler</a></td>`
|
||||
:raw-html:`<td class="yes"></td> <!-- ARM -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Hexagon -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- MBlaze -->`
|
||||
:raw-html:`<td class="no"></td> <!-- MSP430 -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Mips -->`
|
||||
:raw-html:`<td class="na"></td> <!-- NVPTX -->`
|
||||
@ -1848,7 +1844,6 @@ Here is the table:
|
||||
:raw-html:`<td><a href="#feat_inlineasm">inline asm</a></td>`
|
||||
:raw-html:`<td class="yes"></td> <!-- ARM -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- Hexagon -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- MBlaze -->`
|
||||
:raw-html:`<td class="unknown"></td> <!-- MSP430 -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Mips -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- NVPTX -->`
|
||||
@ -1863,7 +1858,6 @@ Here is the table:
|
||||
:raw-html:`<td><a href="#feat_jit">jit</a></td>`
|
||||
:raw-html:`<td class="partial"><a href="#feat_jit_arm">*</a></td> <!-- ARM -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Hexagon -->`
|
||||
:raw-html:`<td class="no"></td> <!-- MBlaze -->`
|
||||
:raw-html:`<td class="unknown"></td> <!-- MSP430 -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- Mips -->`
|
||||
:raw-html:`<td class="na"></td> <!-- NVPTX -->`
|
||||
@ -1878,7 +1872,6 @@ Here is the table:
|
||||
:raw-html:`<td><a href="#feat_objectwrite">.o file writing</a></td>`
|
||||
:raw-html:`<td class="no"></td> <!-- ARM -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Hexagon -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- MBlaze -->`
|
||||
:raw-html:`<td class="no"></td> <!-- MSP430 -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Mips -->`
|
||||
:raw-html:`<td class="na"></td> <!-- NVPTX -->`
|
||||
@ -1893,7 +1886,6 @@ Here is the table:
|
||||
:raw-html:`<td><a hr:raw-html:`ef="#feat_tailcall">tail calls</a></td>`
|
||||
:raw-html:`<td class="yes"></td> <!-- ARM -->`
|
||||
:raw-html:`<td class="yes"></td> <!-- Hexagon -->`
|
||||
:raw-html:`<td class="no"></td> <!-- MBlaze -->`
|
||||
:raw-html:`<td class="unknown"></td> <!-- MSP430 -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Mips -->`
|
||||
:raw-html:`<td class="no"></td> <!-- NVPTX -->`
|
||||
@ -1908,7 +1900,6 @@ Here is the table:
|
||||
:raw-html:`<td><a href="#feat_segstacks">segmented stacks</a></td>`
|
||||
:raw-html:`<td class="no"></td> <!-- ARM -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Hexagon -->`
|
||||
:raw-html:`<td class="no"></td> <!-- MBlaze -->`
|
||||
:raw-html:`<td class="no"></td> <!-- MSP430 -->`
|
||||
:raw-html:`<td class="no"></td> <!-- Mips -->`
|
||||
:raw-html:`<td class="no"></td> <!-- NVPTX -->`
|
||||
|
@ -758,7 +758,7 @@ The following options can be used to set or enable LLVM specific options:
|
||||
target names that you want available in llc. The target names use all lower
|
||||
case. The current set of targets is:
|
||||
|
||||
``arm, cpp, hexagon, mblaze, mips, mipsel, msp430, powerpc, ptx, sparc, spu,
|
||||
``arm, cpp, hexagon, mips, mipsel, msp430, powerpc, ptx, sparc, spu,
|
||||
systemz, x86, x86_64, xcore``.
|
||||
|
||||
``--enable-doxygen``
|
||||
|
@ -64,7 +64,6 @@ public:
|
||||
x86, // X86: i[3-9]86
|
||||
x86_64, // X86-64: amd64, x86_64
|
||||
xcore, // XCore: xcore
|
||||
mblaze, // MBlaze: mblaze
|
||||
nvptx, // NVPTX: 32-bit
|
||||
nvptx64, // NVPTX: 64-bit
|
||||
le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten)
|
||||
|
@ -93,13 +93,6 @@ namespace CallingConv {
|
||||
/// Passes all arguments in register or parameter space.
|
||||
PTX_Device = 72,
|
||||
|
||||
/// MBLAZE_INTR - Calling convention used for MBlaze interrupt routines.
|
||||
MBLAZE_INTR = 73,
|
||||
|
||||
/// MBLAZE_INTR - Calling convention used for MBlaze interrupt support
|
||||
/// routines (i.e. GCC's save_volatiles attribute).
|
||||
MBLAZE_SVOL = 74,
|
||||
|
||||
/// SPIR_FUNC - Calling convention for SPIR non-kernel device functions.
|
||||
/// No lowering or expansion of arguments.
|
||||
/// Structures are passed as a pointer to a struct with the byval attribute.
|
||||
|
@ -276,7 +276,6 @@ enum {
|
||||
EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller
|
||||
EM_TILE64 = 187, // Tilera TILE64 multicore architecture family
|
||||
EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family
|
||||
EM_MICROBLAZE = 189, // Xilinx MicroBlaze 32-bit RISC soft processor core
|
||||
EM_CUDA = 190, // NVIDIA CUDA architecture
|
||||
EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family
|
||||
EM_CLOUDSHIELD = 192, // CloudShield architecture family
|
||||
@ -287,8 +286,7 @@ enum {
|
||||
EM_RL78 = 197, // Renesas RL78 family
|
||||
EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor
|
||||
EM_78KOR = 199, // Renesas 78KOR family
|
||||
EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC)
|
||||
EM_MBLAZE = 47787 // Xilinx MicroBlaze
|
||||
EM_56800EX = 200 // Freescale 56800EX Digital Signal Controller (DSC)
|
||||
};
|
||||
|
||||
// Object file classes.
|
||||
@ -418,32 +416,6 @@ enum {
|
||||
R_386_NUM = 43
|
||||
};
|
||||
|
||||
// MBlaze relocations.
|
||||
enum {
|
||||
R_MICROBLAZE_NONE = 0,
|
||||
R_MICROBLAZE_32 = 1,
|
||||
R_MICROBLAZE_32_PCREL = 2,
|
||||
R_MICROBLAZE_64_PCREL = 3,
|
||||
R_MICROBLAZE_32_PCREL_LO = 4,
|
||||
R_MICROBLAZE_64 = 5,
|
||||
R_MICROBLAZE_32_LO = 6,
|
||||
R_MICROBLAZE_SRO32 = 7,
|
||||
R_MICROBLAZE_SRW32 = 8,
|
||||
R_MICROBLAZE_64_NONE = 9,
|
||||
R_MICROBLAZE_32_SYM_OP_SYM = 10,
|
||||
R_MICROBLAZE_GNU_VTINHERIT = 11,
|
||||
R_MICROBLAZE_GNU_VTENTRY = 12,
|
||||
R_MICROBLAZE_GOTPC_64 = 13,
|
||||
R_MICROBLAZE_GOT_64 = 14,
|
||||
R_MICROBLAZE_PLT_64 = 15,
|
||||
R_MICROBLAZE_REL = 16,
|
||||
R_MICROBLAZE_JUMP_SLOT = 17,
|
||||
R_MICROBLAZE_GLOB_DAT = 18,
|
||||
R_MICROBLAZE_GOTOFF_64 = 19,
|
||||
R_MICROBLAZE_GOTOFF_32 = 20,
|
||||
R_MICROBLAZE_COPY = 21
|
||||
};
|
||||
|
||||
// ELF Relocation types for PPC32
|
||||
enum {
|
||||
R_PPC_NONE = 0, /* No relocation. */
|
||||
|
@ -176,7 +176,6 @@ ScalarEnumerationTraits<ELFYAML::ELF_EM>::enumeration(IO &IO,
|
||||
ECase(EM_STM8)
|
||||
ECase(EM_TILE64)
|
||||
ECase(EM_TILEPRO)
|
||||
ECase(EM_MICROBLAZE)
|
||||
ECase(EM_CUDA)
|
||||
ECase(EM_TILEGX)
|
||||
ECase(EM_CLOUDSHIELD)
|
||||
@ -188,7 +187,6 @@ ScalarEnumerationTraits<ELFYAML::ELF_EM>::enumeration(IO &IO,
|
||||
ECase(EM_VIDEOCORE5)
|
||||
ECase(EM_78KOR)
|
||||
ECase(EM_56800EX)
|
||||
ECase(EM_MBLAZE)
|
||||
#undef ECase
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,6 @@ const char *Triple::getArchTypeName(ArchType Kind) {
|
||||
case x86: return "i386";
|
||||
case x86_64: return "x86_64";
|
||||
case xcore: return "xcore";
|
||||
case mblaze: return "mblaze";
|
||||
case nvptx: return "nvptx";
|
||||
case nvptx64: return "nvptx64";
|
||||
case le32: return "le32";
|
||||
@ -63,8 +62,6 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
|
||||
case ppc64:
|
||||
case ppc: return "ppc";
|
||||
|
||||
case mblaze: return "mblaze";
|
||||
|
||||
case mips:
|
||||
case mipsel:
|
||||
case mips64:
|
||||
@ -171,7 +168,6 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
|
||||
.Case("ppc64", ppc64)
|
||||
.Case("ppc32", ppc)
|
||||
.Case("ppc", ppc)
|
||||
.Case("mblaze", mblaze)
|
||||
.Case("r600", r600)
|
||||
.Case("hexagon", hexagon)
|
||||
.Case("sparc", sparc)
|
||||
@ -201,7 +197,6 @@ const char *Triple::getArchNameForAssembler() {
|
||||
.Case("x86_64", "x86_64")
|
||||
.Case("powerpc", "ppc")
|
||||
.Case("powerpc64", "ppc64")
|
||||
.Cases("mblaze", "microblaze", "mblaze")
|
||||
.Case("arm", "arm")
|
||||
.Cases("armv4t", "thumbv4t", "armv4t")
|
||||
.Cases("armv5", "armv5e", "thumbv5", "thumbv5e", "armv5")
|
||||
@ -225,7 +220,6 @@ static Triple::ArchType parseArch(StringRef ArchName) {
|
||||
.Cases("amd64", "x86_64", Triple::x86_64)
|
||||
.Case("powerpc", Triple::ppc)
|
||||
.Cases("powerpc64", "ppu", Triple::ppc64)
|
||||
.Case("mblaze", Triple::mblaze)
|
||||
.Case("aarch64", Triple::aarch64)
|
||||
.Cases("arm", "xscale", Triple::arm)
|
||||
// FIXME: It would be good to replace these with explicit names for all the
|
||||
@ -678,7 +672,6 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::hexagon:
|
||||
case llvm::Triple::le32:
|
||||
case llvm::Triple::mblaze:
|
||||
case llvm::Triple::mips:
|
||||
case llvm::Triple::mipsel:
|
||||
case llvm::Triple::nvptx:
|
||||
@ -733,7 +726,6 @@ Triple Triple::get32BitArchVariant() const {
|
||||
case Triple::arm:
|
||||
case Triple::hexagon:
|
||||
case Triple::le32:
|
||||
case Triple::mblaze:
|
||||
case Triple::mips:
|
||||
case Triple::mipsel:
|
||||
case Triple::nvptx:
|
||||
@ -766,7 +758,6 @@ Triple Triple::get64BitArchVariant() const {
|
||||
case Triple::arm:
|
||||
case Triple::hexagon:
|
||||
case Triple::le32:
|
||||
case Triple::mblaze:
|
||||
case Triple::msp430:
|
||||
case Triple::r600:
|
||||
case Triple::tce:
|
||||
|
@ -16,7 +16,7 @@
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[common]
|
||||
subdirectories = AArch64 ARM CppBackend Hexagon MBlaze MSP430 NVPTX Mips PowerPC R600 Sparc SystemZ X86 XCore
|
||||
subdirectories = AArch64 ARM CppBackend Hexagon MSP430 NVPTX Mips PowerPC R600 Sparc SystemZ X86 XCore
|
||||
|
||||
; This is a special group whose required libraries are extended (by llvm-build)
|
||||
; with the best execution engine (the native JIT, if available, or the
|
||||
|
@ -1,8 +0,0 @@
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.. )
|
||||
|
||||
add_llvm_library(LLVMMBlazeAsmParser
|
||||
MBlazeAsmParser.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMMBlazeAsmParser MBlazeCommonTableGen)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/MBlaze/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 = MBlazeAsmParser
|
||||
parent = MBlaze
|
||||
required_libraries = MBlazeInfo MC MCParser Support
|
||||
add_to_library_groups = MBlaze
|
@ -1,573 +0,0 @@
|
||||
//===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/MBlazeBaseInfo.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCTargetAsmParser.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
struct MBlazeOperand;
|
||||
|
||||
class MBlazeAsmParser : public MCTargetAsmParser {
|
||||
MCAsmParser &Parser;
|
||||
|
||||
MCAsmParser &getParser() const { return Parser; }
|
||||
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
|
||||
|
||||
void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
|
||||
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
|
||||
|
||||
MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
MBlazeOperand *ParseRegister();
|
||||
MBlazeOperand *ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc);
|
||||
MBlazeOperand *ParseImmediate();
|
||||
MBlazeOperand *ParseFsl();
|
||||
MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
|
||||
virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
|
||||
|
||||
bool ParseDirectiveWord(unsigned Size, SMLoc L);
|
||||
|
||||
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
MCStreamer &Out, unsigned &ErrorInfo,
|
||||
bool MatchingInlineAsm);
|
||||
|
||||
/// @name Auto-generated Match Functions
|
||||
/// {
|
||||
|
||||
#define GET_ASSEMBLER_HEADER
|
||||
#include "MBlazeGenAsmMatcher.inc"
|
||||
|
||||
/// }
|
||||
|
||||
public:
|
||||
MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
|
||||
: MCTargetAsmParser(), Parser(_Parser) {}
|
||||
|
||||
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||
SMLoc NameLoc,
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
|
||||
virtual bool ParseDirective(AsmToken DirectiveID);
|
||||
};
|
||||
|
||||
/// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
|
||||
/// instruction.
|
||||
struct MBlazeOperand : public MCParsedAsmOperand {
|
||||
enum KindTy {
|
||||
Token,
|
||||
Immediate,
|
||||
Register,
|
||||
Memory,
|
||||
Fsl
|
||||
} Kind;
|
||||
|
||||
SMLoc StartLoc, EndLoc;
|
||||
|
||||
struct TokOp {
|
||||
const char *Data;
|
||||
unsigned Length;
|
||||
};
|
||||
|
||||
struct RegOp {
|
||||
unsigned RegNum;
|
||||
};
|
||||
|
||||
struct ImmOp {
|
||||
const MCExpr *Val;
|
||||
};
|
||||
|
||||
struct MemOp {
|
||||
unsigned Base;
|
||||
unsigned OffReg;
|
||||
const MCExpr *Off;
|
||||
};
|
||||
|
||||
struct FslImmOp {
|
||||
const MCExpr *Val;
|
||||
};
|
||||
|
||||
union {
|
||||
struct TokOp Tok;
|
||||
struct RegOp Reg;
|
||||
struct ImmOp Imm;
|
||||
struct MemOp Mem;
|
||||
struct FslImmOp FslImm;
|
||||
};
|
||||
|
||||
MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
|
||||
public:
|
||||
MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
|
||||
Kind = o.Kind;
|
||||
StartLoc = o.StartLoc;
|
||||
EndLoc = o.EndLoc;
|
||||
switch (Kind) {
|
||||
case Register:
|
||||
Reg = o.Reg;
|
||||
break;
|
||||
case Immediate:
|
||||
Imm = o.Imm;
|
||||
break;
|
||||
case Token:
|
||||
Tok = o.Tok;
|
||||
break;
|
||||
case Memory:
|
||||
Mem = o.Mem;
|
||||
break;
|
||||
case Fsl:
|
||||
FslImm = o.FslImm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// getStartLoc - Get the location of the first token of this operand.
|
||||
SMLoc getStartLoc() const { return StartLoc; }
|
||||
|
||||
/// getEndLoc - Get the location of the last token of this operand.
|
||||
SMLoc getEndLoc() const { return EndLoc; }
|
||||
|
||||
unsigned getReg() const {
|
||||
assert(Kind == Register && "Invalid access!");
|
||||
return Reg.RegNum;
|
||||
}
|
||||
|
||||
const MCExpr *getImm() const {
|
||||
assert(Kind == Immediate && "Invalid access!");
|
||||
return Imm.Val;
|
||||
}
|
||||
|
||||
const MCExpr *getFslImm() const {
|
||||
assert(Kind == Fsl && "Invalid access!");
|
||||
return FslImm.Val;
|
||||
}
|
||||
|
||||
unsigned getMemBase() const {
|
||||
assert(Kind == Memory && "Invalid access!");
|
||||
return Mem.Base;
|
||||
}
|
||||
|
||||
const MCExpr* getMemOff() const {
|
||||
assert(Kind == Memory && "Invalid access!");
|
||||
return Mem.Off;
|
||||
}
|
||||
|
||||
unsigned getMemOffReg() const {
|
||||
assert(Kind == Memory && "Invalid access!");
|
||||
return Mem.OffReg;
|
||||
}
|
||||
|
||||
bool isToken() const { return Kind == Token; }
|
||||
bool isImm() const { return Kind == Immediate; }
|
||||
bool isMem() const { return Kind == Memory; }
|
||||
bool isFsl() const { return Kind == Fsl; }
|
||||
bool isReg() const { return Kind == Register; }
|
||||
|
||||
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
|
||||
// Add as immediates when possible. Null MCExpr = 0.
|
||||
if (Expr == 0)
|
||||
Inst.addOperand(MCOperand::CreateImm(0));
|
||||
else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
|
||||
Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
|
||||
else
|
||||
Inst.addOperand(MCOperand::CreateExpr(Expr));
|
||||
}
|
||||
|
||||
void addRegOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateReg(getReg()));
|
||||
}
|
||||
|
||||
void addImmOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
addExpr(Inst, getImm());
|
||||
}
|
||||
|
||||
void addFslOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
addExpr(Inst, getFslImm());
|
||||
}
|
||||
|
||||
void addMemOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
|
||||
Inst.addOperand(MCOperand::CreateReg(getMemBase()));
|
||||
|
||||
unsigned RegOff = getMemOffReg();
|
||||
if (RegOff)
|
||||
Inst.addOperand(MCOperand::CreateReg(RegOff));
|
||||
else
|
||||
addExpr(Inst, getMemOff());
|
||||
}
|
||||
|
||||
StringRef getToken() const {
|
||||
assert(Kind == Token && "Invalid access!");
|
||||
return StringRef(Tok.Data, Tok.Length);
|
||||
}
|
||||
|
||||
virtual void print(raw_ostream &OS) const;
|
||||
|
||||
static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
|
||||
MBlazeOperand *Op = new MBlazeOperand(Token);
|
||||
Op->Tok.Data = Str.data();
|
||||
Op->Tok.Length = Str.size();
|
||||
Op->StartLoc = S;
|
||||
Op->EndLoc = S;
|
||||
return Op;
|
||||
}
|
||||
|
||||
static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
|
||||
MBlazeOperand *Op = new MBlazeOperand(Register);
|
||||
Op->Reg.RegNum = RegNum;
|
||||
Op->StartLoc = S;
|
||||
Op->EndLoc = E;
|
||||
return Op;
|
||||
}
|
||||
|
||||
static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
|
||||
MBlazeOperand *Op = new MBlazeOperand(Immediate);
|
||||
Op->Imm.Val = Val;
|
||||
Op->StartLoc = S;
|
||||
Op->EndLoc = E;
|
||||
return Op;
|
||||
}
|
||||
|
||||
static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
|
||||
MBlazeOperand *Op = new MBlazeOperand(Fsl);
|
||||
Op->Imm.Val = Val;
|
||||
Op->StartLoc = S;
|
||||
Op->EndLoc = E;
|
||||
return Op;
|
||||
}
|
||||
|
||||
static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
|
||||
SMLoc E) {
|
||||
MBlazeOperand *Op = new MBlazeOperand(Memory);
|
||||
Op->Mem.Base = Base;
|
||||
Op->Mem.Off = Off;
|
||||
Op->Mem.OffReg = 0;
|
||||
Op->StartLoc = S;
|
||||
Op->EndLoc = E;
|
||||
return Op;
|
||||
}
|
||||
|
||||
static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
|
||||
SMLoc E) {
|
||||
MBlazeOperand *Op = new MBlazeOperand(Memory);
|
||||
Op->Mem.Base = Base;
|
||||
Op->Mem.OffReg = Off;
|
||||
Op->Mem.Off = 0;
|
||||
Op->StartLoc = S;
|
||||
Op->EndLoc = E;
|
||||
return Op;
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace.
|
||||
|
||||
void MBlazeOperand::print(raw_ostream &OS) const {
|
||||
switch (Kind) {
|
||||
case Immediate:
|
||||
getImm()->print(OS);
|
||||
break;
|
||||
case Register:
|
||||
OS << "<register R";
|
||||
OS << getMBlazeRegisterNumbering(getReg()) << ">";
|
||||
break;
|
||||
case Token:
|
||||
OS << "'" << getToken() << "'";
|
||||
break;
|
||||
case Memory: {
|
||||
OS << "<memory R";
|
||||
OS << getMBlazeRegisterNumbering(getMemBase());
|
||||
OS << ", ";
|
||||
|
||||
unsigned RegOff = getMemOffReg();
|
||||
if (RegOff)
|
||||
OS << "R" << getMBlazeRegisterNumbering(RegOff);
|
||||
else
|
||||
OS << getMemOff();
|
||||
OS << ">";
|
||||
}
|
||||
break;
|
||||
case Fsl:
|
||||
getFslImm()->print(OS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// @name Auto-generated Match Functions
|
||||
/// {
|
||||
|
||||
static unsigned MatchRegisterName(StringRef Name);
|
||||
|
||||
/// }
|
||||
//
|
||||
bool MBlazeAsmParser::
|
||||
MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
MCStreamer &Out, unsigned &ErrorInfo,
|
||||
bool MatchingInlineAsm) {
|
||||
MCInst Inst;
|
||||
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo,
|
||||
MatchingInlineAsm)) {
|
||||
default: break;
|
||||
case Match_Success:
|
||||
Out.EmitInstruction(Inst);
|
||||
return false;
|
||||
case Match_MissingFeature:
|
||||
return Error(IDLoc, "instruction use requires an option to be enabled");
|
||||
case Match_MnemonicFail:
|
||||
return Error(IDLoc, "unrecognized instruction mnemonic");
|
||||
case Match_InvalidOperand: {
|
||||
SMLoc ErrorLoc = IDLoc;
|
||||
if (ErrorInfo != ~0U) {
|
||||
if (ErrorInfo >= Operands.size())
|
||||
return Error(IDLoc, "too few operands for instruction");
|
||||
|
||||
ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
|
||||
if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
|
||||
}
|
||||
|
||||
return Error(ErrorLoc, "invalid operand for instruction");
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("Implement any new match types added!");
|
||||
}
|
||||
|
||||
MBlazeOperand *MBlazeAsmParser::
|
||||
ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
if (Operands.size() != 4)
|
||||
return 0;
|
||||
|
||||
MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
|
||||
MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
|
||||
|
||||
SMLoc S = Base.getStartLoc();
|
||||
SMLoc O = Offset.getStartLoc();
|
||||
SMLoc E = Offset.getEndLoc();
|
||||
|
||||
if (!Base.isReg()) {
|
||||
Error(S, "base address must be a register");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!Offset.isReg() && !Offset.isImm()) {
|
||||
Error(O, "offset must be a register or immediate");
|
||||
return 0;
|
||||
}
|
||||
|
||||
MBlazeOperand *Op;
|
||||
if (Offset.isReg())
|
||||
Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
|
||||
else
|
||||
Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
|
||||
|
||||
delete Operands.pop_back_val();
|
||||
delete Operands.pop_back_val();
|
||||
Operands.push_back(Op);
|
||||
|
||||
return Op;
|
||||
}
|
||||
|
||||
bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
|
||||
SMLoc &StartLoc, SMLoc &EndLoc) {
|
||||
MBlazeOperand *Reg = ParseRegister(StartLoc, EndLoc);
|
||||
if (!Reg)
|
||||
return true;
|
||||
RegNo = Reg->getReg();
|
||||
return false;
|
||||
}
|
||||
|
||||
MBlazeOperand *MBlazeAsmParser::ParseRegister() {
|
||||
SMLoc S, E;
|
||||
return ParseRegister(S, E);
|
||||
}
|
||||
|
||||
MBlazeOperand *MBlazeAsmParser::ParseRegister(SMLoc &StartLoc, SMLoc &EndLoc) {
|
||||
StartLoc = Parser.getTok().getLoc();
|
||||
EndLoc = Parser.getTok().getEndLoc();
|
||||
|
||||
if (getLexer().getKind() != AsmToken::Identifier)
|
||||
return 0;
|
||||
|
||||
unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
|
||||
if (RegNo == 0)
|
||||
return 0;
|
||||
|
||||
getLexer().Lex();
|
||||
return MBlazeOperand::CreateReg(RegNo, StartLoc, EndLoc);
|
||||
}
|
||||
|
||||
static unsigned MatchFslRegister(StringRef String) {
|
||||
if (!String.startswith("rfsl"))
|
||||
return -1;
|
||||
|
||||
unsigned regNum;
|
||||
if (String.substr(4).getAsInteger(10,regNum))
|
||||
return -1;
|
||||
|
||||
return regNum;
|
||||
}
|
||||
|
||||
MBlazeOperand *MBlazeAsmParser::ParseFsl() {
|
||||
SMLoc S = Parser.getTok().getLoc();
|
||||
SMLoc E = Parser.getTok().getEndLoc();
|
||||
|
||||
switch (getLexer().getKind()) {
|
||||
default: return 0;
|
||||
case AsmToken::Identifier:
|
||||
unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
|
||||
if (reg >= 16)
|
||||
return 0;
|
||||
|
||||
getLexer().Lex();
|
||||
const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
|
||||
return MBlazeOperand::CreateFslImm(EVal,S,E);
|
||||
}
|
||||
}
|
||||
|
||||
MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
|
||||
SMLoc S = Parser.getTok().getLoc();
|
||||
SMLoc E = Parser.getTok().getEndLoc();
|
||||
|
||||
const MCExpr *EVal;
|
||||
switch (getLexer().getKind()) {
|
||||
default: return 0;
|
||||
case AsmToken::LParen:
|
||||
case AsmToken::Plus:
|
||||
case AsmToken::Minus:
|
||||
case AsmToken::Integer:
|
||||
case AsmToken::Identifier:
|
||||
if (getParser().parseExpression(EVal))
|
||||
return 0;
|
||||
|
||||
return MBlazeOperand::CreateImm(EVal, S, E);
|
||||
}
|
||||
}
|
||||
|
||||
MBlazeOperand *MBlazeAsmParser::
|
||||
ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
MBlazeOperand *Op;
|
||||
|
||||
// Attempt to parse the next token as a register name
|
||||
Op = ParseRegister();
|
||||
|
||||
// Attempt to parse the next token as an FSL immediate
|
||||
if (!Op)
|
||||
Op = ParseFsl();
|
||||
|
||||
// Attempt to parse the next token as an immediate
|
||||
if (!Op)
|
||||
Op = ParseImmediate();
|
||||
|
||||
// If the token could not be parsed then fail
|
||||
if (!Op) {
|
||||
Error(Parser.getTok().getLoc(), "unknown operand");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Push the parsed operand into the list of operands
|
||||
Operands.push_back(Op);
|
||||
return Op;
|
||||
}
|
||||
|
||||
/// Parse an mblaze instruction mnemonic followed by its operands.
|
||||
bool MBlazeAsmParser::
|
||||
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
// The first operands is the token for the instruction name
|
||||
size_t dotLoc = Name.find('.');
|
||||
Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
|
||||
if (dotLoc < Name.size())
|
||||
Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
|
||||
|
||||
// If there are no more operands then finish
|
||||
if (getLexer().is(AsmToken::EndOfStatement))
|
||||
return false;
|
||||
|
||||
// Parse the first operand
|
||||
if (!ParseOperand(Operands))
|
||||
return true;
|
||||
|
||||
while (getLexer().isNot(AsmToken::EndOfStatement) &&
|
||||
getLexer().is(AsmToken::Comma)) {
|
||||
// Consume the comma token
|
||||
getLexer().Lex();
|
||||
|
||||
// Parse the next operand
|
||||
if (!ParseOperand(Operands))
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the instruction requires a memory operand then we need to
|
||||
// replace the last two operands (base+offset) with a single
|
||||
// memory operand.
|
||||
if (Name.startswith("lw") || Name.startswith("sw") ||
|
||||
Name.startswith("lh") || Name.startswith("sh") ||
|
||||
Name.startswith("lb") || Name.startswith("sb"))
|
||||
return (ParseMemory(Operands) == NULL);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDirective parses the MBlaze specific directives
|
||||
bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
StringRef IDVal = DirectiveID.getIdentifier();
|
||||
if (IDVal == ".word")
|
||||
return ParseDirectiveWord(2, DirectiveID.getLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
/// ParseDirectiveWord
|
||||
/// ::= .word [ expression (, expression)* ]
|
||||
bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
||||
for (;;) {
|
||||
const MCExpr *Value;
|
||||
if (getParser().parseExpression(Value))
|
||||
return true;
|
||||
|
||||
getParser().getStreamer().EmitValue(Value, Size);
|
||||
|
||||
if (getLexer().is(AsmToken::EndOfStatement))
|
||||
break;
|
||||
|
||||
// FIXME: Improve diagnostic.
|
||||
if (getLexer().isNot(AsmToken::Comma))
|
||||
return Error(L, "unexpected token in directive");
|
||||
Parser.Lex();
|
||||
}
|
||||
}
|
||||
|
||||
Parser.Lex();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Force static initialization.
|
||||
extern "C" void LLVMInitializeMBlazeAsmParser() {
|
||||
RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
|
||||
}
|
||||
|
||||
#define GET_REGISTER_MATCHER
|
||||
#define GET_MATCHER_IMPLEMENTATION
|
||||
#include "MBlazeGenAsmMatcher.inc"
|
@ -1,15 +0,0 @@
|
||||
##===- lib/Target/MBlaze/AsmParser/Makefile ----------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../../..
|
||||
LIBRARYNAME = LLVMMBlazeAsmParser
|
||||
|
||||
# Hack: we need to include 'main' MBlaze target directory for private headers
|
||||
CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
@ -1,37 +0,0 @@
|
||||
set(LLVM_TARGET_DEFINITIONS MBlaze.td)
|
||||
|
||||
tablegen(LLVM MBlazeGenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM MBlazeGenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM MBlazeGenCodeEmitter.inc -gen-emitter)
|
||||
tablegen(LLVM MBlazeGenAsmWriter.inc -gen-asm-writer)
|
||||
tablegen(LLVM MBlazeGenAsmMatcher.inc -gen-asm-matcher)
|
||||
tablegen(LLVM MBlazeGenDAGISel.inc -gen-dag-isel)
|
||||
tablegen(LLVM MBlazeGenCallingConv.inc -gen-callingconv)
|
||||
tablegen(LLVM MBlazeGenSubtargetInfo.inc -gen-subtarget)
|
||||
tablegen(LLVM MBlazeGenIntrinsics.inc -gen-tgt-intrinsic)
|
||||
add_public_tablegen_target(MBlazeCommonTableGen)
|
||||
|
||||
add_llvm_target(MBlazeCodeGen
|
||||
MBlazeDelaySlotFiller.cpp
|
||||
MBlazeInstrInfo.cpp
|
||||
MBlazeISelDAGToDAG.cpp
|
||||
MBlazeISelLowering.cpp
|
||||
MBlazeFrameLowering.cpp
|
||||
MBlazeMachineFunction.cpp
|
||||
MBlazeRegisterInfo.cpp
|
||||
MBlazeSubtarget.cpp
|
||||
MBlazeTargetMachine.cpp
|
||||
MBlazeTargetObjectFile.cpp
|
||||
MBlazeIntrinsicInfo.cpp
|
||||
MBlazeSelectionDAGInfo.cpp
|
||||
MBlazeAsmPrinter.cpp
|
||||
MBlazeMCInstLower.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMMBlazeCodeGen intrinsics_gen)
|
||||
|
||||
add_subdirectory(AsmParser)
|
||||
add_subdirectory(Disassembler)
|
||||
add_subdirectory(InstPrinter)
|
||||
add_subdirectory(TargetInfo)
|
||||
add_subdirectory(MCTargetDesc)
|
@ -1,16 +0,0 @@
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.. )
|
||||
|
||||
add_llvm_library(LLVMMBlazeDisassembler
|
||||
MBlazeDisassembler.cpp
|
||||
)
|
||||
|
||||
# workaround for hanging compilation on MSVC9 and 10
|
||||
if( MSVC_VERSION EQUAL 1500 OR MSVC_VERSION EQUAL 1600 )
|
||||
set_property(
|
||||
SOURCE MBlazeDisassembler.cpp
|
||||
PROPERTY COMPILE_FLAGS "/Od"
|
||||
)
|
||||
endif()
|
||||
|
||||
add_dependencies(LLVMMBlazeDisassembler MBlazeCommonTableGen)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/MBlaze/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 = MBlazeDisassembler
|
||||
parent = MBlaze
|
||||
required_libraries = MBlazeDesc MBlazeInfo MC Support
|
||||
add_to_library_groups = MBlaze
|
@ -1,718 +0,0 @@
|
||||
//===-- MBlazeDisassembler.cpp - Disassembler for MicroBlaze -------------===//
|
||||
//
|
||||
// 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 MBlaze Disassembler. It contains code to translate
|
||||
// the data produced by the decoder into MCInsts.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeDisassembler.h"
|
||||
#include "MBlaze.h"
|
||||
#include "llvm/MC/MCDisassembler.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/MemoryObject.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
// #include "MBlazeGenDecoderTables.inc"
|
||||
// #include "MBlazeGenRegisterNames.inc"
|
||||
|
||||
namespace llvm {
|
||||
extern const MCInstrDesc MBlazeInsts[];
|
||||
}
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
const uint16_t UNSUPPORTED = -1;
|
||||
|
||||
static const uint16_t mblazeBinary2Opcode[] = {
|
||||
MBlaze::ADD, MBlaze::RSUB, MBlaze::ADDC, MBlaze::RSUBC, //00,01,02,03
|
||||
MBlaze::ADDK, MBlaze::RSUBK, MBlaze::ADDKC, MBlaze::RSUBKC, //04,05,06,07
|
||||
MBlaze::ADDI, MBlaze::RSUBI, MBlaze::ADDIC, MBlaze::RSUBIC, //08,09,0A,0B
|
||||
MBlaze::ADDIK, MBlaze::RSUBIK, MBlaze::ADDIKC, MBlaze::RSUBIKC, //0C,0D,0E,0F
|
||||
|
||||
MBlaze::MUL, MBlaze::BSRL, MBlaze::IDIV, MBlaze::GETD, //10,11,12,13
|
||||
UNSUPPORTED, UNSUPPORTED, MBlaze::FADD, UNSUPPORTED, //14,15,16,17
|
||||
MBlaze::MULI, MBlaze::BSRLI, UNSUPPORTED, MBlaze::GET, //18,19,1A,1B
|
||||
UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, //1C,1D,1E,1F
|
||||
|
||||
MBlaze::OR, MBlaze::AND, MBlaze::XOR, MBlaze::ANDN, //20,21,22,23
|
||||
MBlaze::SEXT8, MBlaze::MFS, MBlaze::BR, MBlaze::BEQ, //24,25,26,27
|
||||
MBlaze::ORI, MBlaze::ANDI, MBlaze::XORI, MBlaze::ANDNI, //28,29,2A,2B
|
||||
MBlaze::IMM, MBlaze::RTSD, MBlaze::BRI, MBlaze::BEQI, //2C,2D,2E,2F
|
||||
|
||||
MBlaze::LBU, MBlaze::LHU, MBlaze::LW, UNSUPPORTED, //30,31,32,33
|
||||
MBlaze::SB, MBlaze::SH, MBlaze::SW, UNSUPPORTED, //34,35,36,37
|
||||
MBlaze::LBUI, MBlaze::LHUI, MBlaze::LWI, UNSUPPORTED, //38,39,3A,3B
|
||||
MBlaze::SBI, MBlaze::SHI, MBlaze::SWI, UNSUPPORTED, //3C,3D,3E,3F
|
||||
};
|
||||
|
||||
static unsigned getRD(uint32_t insn) {
|
||||
if (!isMBlazeRegister((insn>>21)&0x1F))
|
||||
return UNSUPPORTED;
|
||||
return getMBlazeRegisterFromNumbering((insn>>21)&0x1F);
|
||||
}
|
||||
|
||||
static unsigned getRA(uint32_t insn) {
|
||||
if (!getMBlazeRegisterFromNumbering((insn>>16)&0x1F))
|
||||
return UNSUPPORTED;
|
||||
return getMBlazeRegisterFromNumbering((insn>>16)&0x1F);
|
||||
}
|
||||
|
||||
static unsigned getRB(uint32_t insn) {
|
||||
if (!getMBlazeRegisterFromNumbering((insn>>11)&0x1F))
|
||||
return UNSUPPORTED;
|
||||
return getMBlazeRegisterFromNumbering((insn>>11)&0x1F);
|
||||
}
|
||||
|
||||
static int64_t getRS(uint32_t insn) {
|
||||
if (!isSpecialMBlazeRegister(insn&0x3FFF))
|
||||
return UNSUPPORTED;
|
||||
return getSpecialMBlazeRegisterFromNumbering(insn&0x3FFF);
|
||||
}
|
||||
|
||||
static int64_t getIMM(uint32_t insn) {
|
||||
int16_t val = (insn & 0xFFFF);
|
||||
return val;
|
||||
}
|
||||
|
||||
static int64_t getSHT(uint32_t insn) {
|
||||
int16_t val = (insn & 0x1F);
|
||||
return val;
|
||||
}
|
||||
|
||||
static unsigned getFLAGS(int32_t insn) {
|
||||
return (insn & 0x7FF);
|
||||
}
|
||||
|
||||
static int64_t getFSL(uint32_t insn) {
|
||||
int16_t val = (insn & 0xF);
|
||||
return val;
|
||||
}
|
||||
|
||||
static unsigned decodeMUL(uint32_t insn) {
|
||||
switch (getFLAGS(insn)) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0: return MBlaze::MUL;
|
||||
case 1: return MBlaze::MULH;
|
||||
case 2: return MBlaze::MULHSU;
|
||||
case 3: return MBlaze::MULHU;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeSEXT(uint32_t insn) {
|
||||
switch (insn&0x7FF) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x60: return MBlaze::SEXT8;
|
||||
case 0x68: return MBlaze::WIC;
|
||||
case 0x64: return MBlaze::WDC;
|
||||
case 0x66: return MBlaze::WDCC;
|
||||
case 0x74: return MBlaze::WDCF;
|
||||
case 0x61: return MBlaze::SEXT16;
|
||||
case 0x41: return MBlaze::SRL;
|
||||
case 0x21: return MBlaze::SRC;
|
||||
case 0x01: return MBlaze::SRA;
|
||||
case 0xE0: return MBlaze::CLZ;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeBEQ(uint32_t insn) {
|
||||
switch ((insn>>21)&0x1F) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x00: return MBlaze::BEQ;
|
||||
case 0x10: return MBlaze::BEQD;
|
||||
case 0x05: return MBlaze::BGE;
|
||||
case 0x15: return MBlaze::BGED;
|
||||
case 0x04: return MBlaze::BGT;
|
||||
case 0x14: return MBlaze::BGTD;
|
||||
case 0x03: return MBlaze::BLE;
|
||||
case 0x13: return MBlaze::BLED;
|
||||
case 0x02: return MBlaze::BLT;
|
||||
case 0x12: return MBlaze::BLTD;
|
||||
case 0x01: return MBlaze::BNE;
|
||||
case 0x11: return MBlaze::BNED;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeBEQI(uint32_t insn) {
|
||||
switch ((insn>>21)&0x1F) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x00: return MBlaze::BEQI;
|
||||
case 0x10: return MBlaze::BEQID;
|
||||
case 0x05: return MBlaze::BGEI;
|
||||
case 0x15: return MBlaze::BGEID;
|
||||
case 0x04: return MBlaze::BGTI;
|
||||
case 0x14: return MBlaze::BGTID;
|
||||
case 0x03: return MBlaze::BLEI;
|
||||
case 0x13: return MBlaze::BLEID;
|
||||
case 0x02: return MBlaze::BLTI;
|
||||
case 0x12: return MBlaze::BLTID;
|
||||
case 0x01: return MBlaze::BNEI;
|
||||
case 0x11: return MBlaze::BNEID;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeBR(uint32_t insn) {
|
||||
switch ((insn>>16)&0x1F) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x00: return MBlaze::BR;
|
||||
case 0x08: return MBlaze::BRA;
|
||||
case 0x0C: return MBlaze::BRK;
|
||||
case 0x10: return MBlaze::BRD;
|
||||
case 0x14: return MBlaze::BRLD;
|
||||
case 0x18: return MBlaze::BRAD;
|
||||
case 0x1C: return MBlaze::BRALD;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeBRI(uint32_t insn) {
|
||||
switch (insn&0x3FFFFFF) {
|
||||
default: break;
|
||||
case 0x0020004: return MBlaze::IDMEMBAR;
|
||||
case 0x0220004: return MBlaze::DMEMBAR;
|
||||
case 0x0420004: return MBlaze::IMEMBAR;
|
||||
}
|
||||
|
||||
switch ((insn>>16)&0x1F) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x00: return MBlaze::BRI;
|
||||
case 0x08: return MBlaze::BRAI;
|
||||
case 0x0C: return MBlaze::BRKI;
|
||||
case 0x10: return MBlaze::BRID;
|
||||
case 0x14: return MBlaze::BRLID;
|
||||
case 0x18: return MBlaze::BRAID;
|
||||
case 0x1C: return MBlaze::BRALID;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeBSRL(uint32_t insn) {
|
||||
switch ((insn>>9)&0x3) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x2: return MBlaze::BSLL;
|
||||
case 0x1: return MBlaze::BSRA;
|
||||
case 0x0: return MBlaze::BSRL;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeBSRLI(uint32_t insn) {
|
||||
switch ((insn>>9)&0x3) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x2: return MBlaze::BSLLI;
|
||||
case 0x1: return MBlaze::BSRAI;
|
||||
case 0x0: return MBlaze::BSRLI;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeRSUBK(uint32_t insn) {
|
||||
switch (getFLAGS(insn)) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::RSUBK;
|
||||
case 0x1: return MBlaze::CMP;
|
||||
case 0x3: return MBlaze::CMPU;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeFADD(uint32_t insn) {
|
||||
switch (getFLAGS(insn)) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x000: return MBlaze::FADD;
|
||||
case 0x080: return MBlaze::FRSUB;
|
||||
case 0x100: return MBlaze::FMUL;
|
||||
case 0x180: return MBlaze::FDIV;
|
||||
case 0x200: return MBlaze::FCMP_UN;
|
||||
case 0x210: return MBlaze::FCMP_LT;
|
||||
case 0x220: return MBlaze::FCMP_EQ;
|
||||
case 0x230: return MBlaze::FCMP_LE;
|
||||
case 0x240: return MBlaze::FCMP_GT;
|
||||
case 0x250: return MBlaze::FCMP_NE;
|
||||
case 0x260: return MBlaze::FCMP_GE;
|
||||
case 0x280: return MBlaze::FLT;
|
||||
case 0x300: return MBlaze::FINT;
|
||||
case 0x380: return MBlaze::FSQRT;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeGET(uint32_t insn) {
|
||||
switch ((insn>>10)&0x3F) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x00: return MBlaze::GET;
|
||||
case 0x01: return MBlaze::EGET;
|
||||
case 0x02: return MBlaze::AGET;
|
||||
case 0x03: return MBlaze::EAGET;
|
||||
case 0x04: return MBlaze::TGET;
|
||||
case 0x05: return MBlaze::TEGET;
|
||||
case 0x06: return MBlaze::TAGET;
|
||||
case 0x07: return MBlaze::TEAGET;
|
||||
case 0x08: return MBlaze::CGET;
|
||||
case 0x09: return MBlaze::ECGET;
|
||||
case 0x0A: return MBlaze::CAGET;
|
||||
case 0x0B: return MBlaze::ECAGET;
|
||||
case 0x0C: return MBlaze::TCGET;
|
||||
case 0x0D: return MBlaze::TECGET;
|
||||
case 0x0E: return MBlaze::TCAGET;
|
||||
case 0x0F: return MBlaze::TECAGET;
|
||||
case 0x10: return MBlaze::NGET;
|
||||
case 0x11: return MBlaze::NEGET;
|
||||
case 0x12: return MBlaze::NAGET;
|
||||
case 0x13: return MBlaze::NEAGET;
|
||||
case 0x14: return MBlaze::TNGET;
|
||||
case 0x15: return MBlaze::TNEGET;
|
||||
case 0x16: return MBlaze::TNAGET;
|
||||
case 0x17: return MBlaze::TNEAGET;
|
||||
case 0x18: return MBlaze::NCGET;
|
||||
case 0x19: return MBlaze::NECGET;
|
||||
case 0x1A: return MBlaze::NCAGET;
|
||||
case 0x1B: return MBlaze::NECAGET;
|
||||
case 0x1C: return MBlaze::TNCGET;
|
||||
case 0x1D: return MBlaze::TNECGET;
|
||||
case 0x1E: return MBlaze::TNCAGET;
|
||||
case 0x1F: return MBlaze::TNECAGET;
|
||||
case 0x20: return MBlaze::PUT;
|
||||
case 0x22: return MBlaze::APUT;
|
||||
case 0x24: return MBlaze::TPUT;
|
||||
case 0x26: return MBlaze::TAPUT;
|
||||
case 0x28: return MBlaze::CPUT;
|
||||
case 0x2A: return MBlaze::CAPUT;
|
||||
case 0x2C: return MBlaze::TCPUT;
|
||||
case 0x2E: return MBlaze::TCAPUT;
|
||||
case 0x30: return MBlaze::NPUT;
|
||||
case 0x32: return MBlaze::NAPUT;
|
||||
case 0x34: return MBlaze::TNPUT;
|
||||
case 0x36: return MBlaze::TNAPUT;
|
||||
case 0x38: return MBlaze::NCPUT;
|
||||
case 0x3A: return MBlaze::NCAPUT;
|
||||
case 0x3C: return MBlaze::TNCPUT;
|
||||
case 0x3E: return MBlaze::TNCAPUT;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeGETD(uint32_t insn) {
|
||||
switch ((insn>>5)&0x3F) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x00: return MBlaze::GETD;
|
||||
case 0x01: return MBlaze::EGETD;
|
||||
case 0x02: return MBlaze::AGETD;
|
||||
case 0x03: return MBlaze::EAGETD;
|
||||
case 0x04: return MBlaze::TGETD;
|
||||
case 0x05: return MBlaze::TEGETD;
|
||||
case 0x06: return MBlaze::TAGETD;
|
||||
case 0x07: return MBlaze::TEAGETD;
|
||||
case 0x08: return MBlaze::CGETD;
|
||||
case 0x09: return MBlaze::ECGETD;
|
||||
case 0x0A: return MBlaze::CAGETD;
|
||||
case 0x0B: return MBlaze::ECAGETD;
|
||||
case 0x0C: return MBlaze::TCGETD;
|
||||
case 0x0D: return MBlaze::TECGETD;
|
||||
case 0x0E: return MBlaze::TCAGETD;
|
||||
case 0x0F: return MBlaze::TECAGETD;
|
||||
case 0x10: return MBlaze::NGETD;
|
||||
case 0x11: return MBlaze::NEGETD;
|
||||
case 0x12: return MBlaze::NAGETD;
|
||||
case 0x13: return MBlaze::NEAGETD;
|
||||
case 0x14: return MBlaze::TNGETD;
|
||||
case 0x15: return MBlaze::TNEGETD;
|
||||
case 0x16: return MBlaze::TNAGETD;
|
||||
case 0x17: return MBlaze::TNEAGETD;
|
||||
case 0x18: return MBlaze::NCGETD;
|
||||
case 0x19: return MBlaze::NECGETD;
|
||||
case 0x1A: return MBlaze::NCAGETD;
|
||||
case 0x1B: return MBlaze::NECAGETD;
|
||||
case 0x1C: return MBlaze::TNCGETD;
|
||||
case 0x1D: return MBlaze::TNECGETD;
|
||||
case 0x1E: return MBlaze::TNCAGETD;
|
||||
case 0x1F: return MBlaze::TNECAGETD;
|
||||
case 0x20: return MBlaze::PUTD;
|
||||
case 0x22: return MBlaze::APUTD;
|
||||
case 0x24: return MBlaze::TPUTD;
|
||||
case 0x26: return MBlaze::TAPUTD;
|
||||
case 0x28: return MBlaze::CPUTD;
|
||||
case 0x2A: return MBlaze::CAPUTD;
|
||||
case 0x2C: return MBlaze::TCPUTD;
|
||||
case 0x2E: return MBlaze::TCAPUTD;
|
||||
case 0x30: return MBlaze::NPUTD;
|
||||
case 0x32: return MBlaze::NAPUTD;
|
||||
case 0x34: return MBlaze::TNPUTD;
|
||||
case 0x36: return MBlaze::TNAPUTD;
|
||||
case 0x38: return MBlaze::NCPUTD;
|
||||
case 0x3A: return MBlaze::NCAPUTD;
|
||||
case 0x3C: return MBlaze::TNCPUTD;
|
||||
case 0x3E: return MBlaze::TNCAPUTD;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeIDIV(uint32_t insn) {
|
||||
switch (insn&0x3) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::IDIV;
|
||||
case 0x2: return MBlaze::IDIVU;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeLBU(uint32_t insn) {
|
||||
switch ((insn>>9)&0x1) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::LBU;
|
||||
case 0x1: return MBlaze::LBUR;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeLHU(uint32_t insn) {
|
||||
switch ((insn>>9)&0x1) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::LHU;
|
||||
case 0x1: return MBlaze::LHUR;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeLW(uint32_t insn) {
|
||||
switch ((insn>>9)&0x3) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::LW;
|
||||
case 0x1: return MBlaze::LWR;
|
||||
case 0x2: return MBlaze::LWX;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeSB(uint32_t insn) {
|
||||
switch ((insn>>9)&0x1) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::SB;
|
||||
case 0x1: return MBlaze::SBR;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeSH(uint32_t insn) {
|
||||
switch ((insn>>9)&0x1) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::SH;
|
||||
case 0x1: return MBlaze::SHR;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeSW(uint32_t insn) {
|
||||
switch ((insn>>9)&0x3) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::SW;
|
||||
case 0x1: return MBlaze::SWR;
|
||||
case 0x2: return MBlaze::SWX;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeMFS(uint32_t insn) {
|
||||
switch ((insn>>15)&0x1) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0:
|
||||
switch ((insn>>16)&0x1) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::MSRSET;
|
||||
case 0x1: return MBlaze::MSRCLR;
|
||||
}
|
||||
case 0x1:
|
||||
switch ((insn>>14)&0x1) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x0: return MBlaze::MFS;
|
||||
case 0x1: return MBlaze::MTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeOR(uint32_t insn) {
|
||||
switch (getFLAGS(insn)) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x000: return MBlaze::OR;
|
||||
case 0x400: return MBlaze::PCMPBF;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeXOR(uint32_t insn) {
|
||||
switch (getFLAGS(insn)) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x000: return MBlaze::XOR;
|
||||
case 0x400: return MBlaze::PCMPEQ;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeANDN(uint32_t insn) {
|
||||
switch (getFLAGS(insn)) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x000: return MBlaze::ANDN;
|
||||
case 0x400: return MBlaze::PCMPNE;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned decodeRTSD(uint32_t insn) {
|
||||
switch ((insn>>21)&0x1F) {
|
||||
default: return UNSUPPORTED;
|
||||
case 0x10: return MBlaze::RTSD;
|
||||
case 0x11: return MBlaze::RTID;
|
||||
case 0x12: return MBlaze::RTBD;
|
||||
case 0x14: return MBlaze::RTED;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getOPCODE(uint32_t insn) {
|
||||
unsigned opcode = mblazeBinary2Opcode[ (insn>>26)&0x3F ];
|
||||
switch (opcode) {
|
||||
case MBlaze::MUL: return decodeMUL(insn);
|
||||
case MBlaze::SEXT8: return decodeSEXT(insn);
|
||||
case MBlaze::BEQ: return decodeBEQ(insn);
|
||||
case MBlaze::BEQI: return decodeBEQI(insn);
|
||||
case MBlaze::BR: return decodeBR(insn);
|
||||
case MBlaze::BRI: return decodeBRI(insn);
|
||||
case MBlaze::BSRL: return decodeBSRL(insn);
|
||||
case MBlaze::BSRLI: return decodeBSRLI(insn);
|
||||
case MBlaze::RSUBK: return decodeRSUBK(insn);
|
||||
case MBlaze::FADD: return decodeFADD(insn);
|
||||
case MBlaze::GET: return decodeGET(insn);
|
||||
case MBlaze::GETD: return decodeGETD(insn);
|
||||
case MBlaze::IDIV: return decodeIDIV(insn);
|
||||
case MBlaze::LBU: return decodeLBU(insn);
|
||||
case MBlaze::LHU: return decodeLHU(insn);
|
||||
case MBlaze::LW: return decodeLW(insn);
|
||||
case MBlaze::SB: return decodeSB(insn);
|
||||
case MBlaze::SH: return decodeSH(insn);
|
||||
case MBlaze::SW: return decodeSW(insn);
|
||||
case MBlaze::MFS: return decodeMFS(insn);
|
||||
case MBlaze::OR: return decodeOR(insn);
|
||||
case MBlaze::XOR: return decodeXOR(insn);
|
||||
case MBlaze::ANDN: return decodeANDN(insn);
|
||||
case MBlaze::RTSD: return decodeRTSD(insn);
|
||||
default: return opcode;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Public interface for the disassembler
|
||||
//
|
||||
|
||||
MCDisassembler::DecodeStatus MBlazeDisassembler::getInstruction(MCInst &instr,
|
||||
uint64_t &size,
|
||||
const MemoryObject ®ion,
|
||||
uint64_t address,
|
||||
raw_ostream &vStream,
|
||||
raw_ostream &cStream) const {
|
||||
// The machine instruction.
|
||||
uint32_t insn;
|
||||
uint8_t bytes[4];
|
||||
|
||||
// By default we consume 1 byte on failure
|
||||
size = 1;
|
||||
|
||||
// We want to read exactly 4 bytes of data.
|
||||
if (region.readBytes(address, 4, bytes) == -1)
|
||||
return Fail;
|
||||
|
||||
// Encoded as a big-endian 32-bit word in the stream.
|
||||
insn = (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<< 8) | (bytes[3]<<0);
|
||||
|
||||
// Get the MCInst opcode from the binary instruction and make sure
|
||||
// that it is a valid instruction.
|
||||
unsigned opcode = getOPCODE(insn);
|
||||
if (opcode == UNSUPPORTED)
|
||||
return Fail;
|
||||
|
||||
instr.setOpcode(opcode);
|
||||
|
||||
unsigned RD = getRD(insn);
|
||||
unsigned RA = getRA(insn);
|
||||
unsigned RB = getRB(insn);
|
||||
unsigned RS = getRS(insn);
|
||||
|
||||
uint64_t tsFlags = MBlazeInsts[opcode].TSFlags;
|
||||
switch ((tsFlags & MBlazeII::FormMask)) {
|
||||
default:
|
||||
return Fail;
|
||||
|
||||
case MBlazeII::FC:
|
||||
break;
|
||||
|
||||
case MBlazeII::FRRRR:
|
||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateReg(RB));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRRR:
|
||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
instr.addOperand(MCOperand::CreateReg(RB));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRR:
|
||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRI:
|
||||
switch (opcode) {
|
||||
default:
|
||||
return Fail;
|
||||
case MBlaze::MFS:
|
||||
if (RD == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
|
||||
break;
|
||||
case MBlaze::MTS:
|
||||
if (RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
break;
|
||||
case MBlaze::MSRSET:
|
||||
case MBlaze::MSRCLR:
|
||||
if (RD == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateImm(insn&0x7FFF));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MBlazeII::FRRI:
|
||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
switch (opcode) {
|
||||
default:
|
||||
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
||||
break;
|
||||
case MBlaze::BSRLI:
|
||||
case MBlaze::BSRAI:
|
||||
case MBlaze::BSLLI:
|
||||
instr.addOperand(MCOperand::CreateImm(insn&0x1F));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MBlazeII::FCRR:
|
||||
if (RA == UNSUPPORTED || RB == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
instr.addOperand(MCOperand::CreateReg(RB));
|
||||
break;
|
||||
|
||||
case MBlazeII::FCRI:
|
||||
if (RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRCR:
|
||||
if (RD == UNSUPPORTED || RB == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateReg(RB));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRCI:
|
||||
if (RD == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
||||
break;
|
||||
|
||||
case MBlazeII::FCCR:
|
||||
if (RB == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RB));
|
||||
break;
|
||||
|
||||
case MBlazeII::FCCI:
|
||||
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRRCI:
|
||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
instr.addOperand(MCOperand::CreateImm(getSHT(insn)));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRRC:
|
||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRCX:
|
||||
if (RD == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRCS:
|
||||
if (RD == UNSUPPORTED || RS == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateReg(RS));
|
||||
break;
|
||||
|
||||
case MBlazeII::FCRCS:
|
||||
if (RS == UNSUPPORTED || RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RS));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
break;
|
||||
|
||||
case MBlazeII::FCRCX:
|
||||
if (RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
|
||||
break;
|
||||
|
||||
case MBlazeII::FCX:
|
||||
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
|
||||
break;
|
||||
|
||||
case MBlazeII::FCR:
|
||||
if (RB == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RB));
|
||||
break;
|
||||
|
||||
case MBlazeII::FRIR:
|
||||
if (RD == UNSUPPORTED || RA == UNSUPPORTED)
|
||||
return Fail;
|
||||
instr.addOperand(MCOperand::CreateReg(RD));
|
||||
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
|
||||
instr.addOperand(MCOperand::CreateReg(RA));
|
||||
break;
|
||||
}
|
||||
|
||||
// We always consume 4 bytes of data on success
|
||||
size = 4;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static MCDisassembler *createMBlazeDisassembler(const Target &T,
|
||||
const MCSubtargetInfo &STI) {
|
||||
return new MBlazeDisassembler(STI);
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeMBlazeDisassembler() {
|
||||
// Register the disassembler.
|
||||
TargetRegistry::RegisterMCDisassembler(TheMBlazeTarget,
|
||||
createMBlazeDisassembler);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
//===-- MBlazeDisassembler.h - Disassembler for MicroBlaze -----*- 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 MBlaze Disassembler. It it the header for
|
||||
// MBlazeDisassembler, a subclass of MCDisassembler.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZEDISASSEMBLER_H
|
||||
#define MBLAZEDISASSEMBLER_H
|
||||
|
||||
#include "llvm/MC/MCDisassembler.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCInst;
|
||||
class MemoryObject;
|
||||
class raw_ostream;
|
||||
|
||||
/// MBlazeDisassembler - Disassembler for all MBlaze platforms.
|
||||
class MBlazeDisassembler : public MCDisassembler {
|
||||
public:
|
||||
/// Constructor - Initializes the disassembler.
|
||||
///
|
||||
MBlazeDisassembler(const MCSubtargetInfo &STI) :
|
||||
MCDisassembler(STI) {
|
||||
}
|
||||
|
||||
~MBlazeDisassembler() {
|
||||
}
|
||||
|
||||
/// getInstruction - See MCDisassembler.
|
||||
MCDisassembler::DecodeStatus getInstruction(MCInst &instr,
|
||||
uint64_t &size,
|
||||
const MemoryObject ®ion,
|
||||
uint64_t address,
|
||||
raw_ostream &vStream,
|
||||
raw_ostream &cStream) const;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
##===- lib/Target/MBlaze/Disassembler/Makefile -------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL = ../../../..
|
||||
LIBRARYNAME = LLVMMBlazeDisassembler
|
||||
|
||||
# Hack: we need to include 'main' MBlaze target directory to grab headers
|
||||
CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
@ -1,8 +0,0 @@
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.. )
|
||||
|
||||
add_llvm_library(LLVMMBlazeAsmPrinter
|
||||
MBlazeInstPrinter.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMMBlazeAsmPrinter MBlazeCommonTableGen)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/MBlaze/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 = MBlazeAsmPrinter
|
||||
parent = MBlaze
|
||||
required_libraries = MC Support
|
||||
add_to_library_groups = MBlaze
|
@ -1,71 +0,0 @@
|
||||
//===-- MBlazeInstPrinter.cpp - Convert MBlaze MCInst to assembly syntax --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints an MBlaze MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
#include "MBlazeInstPrinter.h"
|
||||
#include "MBlaze.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
using namespace llvm;
|
||||
|
||||
|
||||
// Include the auto-generated portion of the assembly writer.
|
||||
#include "MBlazeGenAsmWriter.inc"
|
||||
|
||||
void MBlazeInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
||||
StringRef Annot) {
|
||||
printInstruction(MI, O);
|
||||
printAnnotation(O, Annot);
|
||||
}
|
||||
|
||||
void MBlazeInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O, const char *Modifier) {
|
||||
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isReg()) {
|
||||
O << getRegisterName(Op.getReg());
|
||||
} else if (Op.isImm()) {
|
||||
O << (int32_t)Op.getImm();
|
||||
} else {
|
||||
assert(Op.isExpr() && "unknown operand kind in printOperand");
|
||||
O << *Op.getExpr();
|
||||
}
|
||||
}
|
||||
|
||||
void MBlazeInstPrinter::printFSLImm(const MCInst *MI, int OpNo,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO = MI->getOperand(OpNo);
|
||||
if (MO.isImm())
|
||||
O << "rfsl" << MO.getImm();
|
||||
else
|
||||
printOperand(MI, OpNo, O, NULL);
|
||||
}
|
||||
|
||||
void MBlazeInstPrinter::printUnsignedImm(const MCInst *MI, int OpNo,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO = MI->getOperand(OpNo);
|
||||
if (MO.isImm())
|
||||
O << (uint32_t)MO.getImm();
|
||||
else
|
||||
printOperand(MI, OpNo, O, NULL);
|
||||
}
|
||||
|
||||
void MBlazeInstPrinter::printMemOperand(const MCInst *MI, int OpNo,
|
||||
raw_ostream &O, const char *Modifier) {
|
||||
printOperand(MI, OpNo, O, NULL);
|
||||
O << ", ";
|
||||
printOperand(MI, OpNo+1, O, NULL);
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
//= MBlazeInstPrinter.h - Convert MBlaze MCInst to assembly syntax -*- C++ -*-//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints a MBlaze MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZEINSTPRINTER_H
|
||||
#define MBLAZEINSTPRINTER_H
|
||||
|
||||
#include "llvm/MC/MCInstPrinter.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCOperand;
|
||||
|
||||
class MBlazeInstPrinter : public MCInstPrinter {
|
||||
public:
|
||||
MBlazeInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI)
|
||||
: MCInstPrinter(MAI, MII, MRI) {}
|
||||
|
||||
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
|
||||
|
||||
// Autogenerated by tblgen.
|
||||
void printInstruction(const MCInst *MI, raw_ostream &O);
|
||||
static const char *getRegisterName(unsigned RegNo);
|
||||
|
||||
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
void printFSLImm(const MCInst *MI, int OpNo, raw_ostream &O);
|
||||
void printUnsignedImm(const MCInst *MI, int OpNo, raw_ostream &O);
|
||||
void printMemOperand(const MCInst *MI, int OpNo,raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
##===- lib/Target/MBlaze/AsmPrinter/Makefile ---------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../../..
|
||||
LIBRARYNAME = LLVMMBlazeAsmPrinter
|
||||
|
||||
# Hack: we need to include 'main' MBlaze target directory to grab
|
||||
# private headers
|
||||
CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
@ -1,34 +0,0 @@
|
||||
;===- ./lib/Target/MBlaze/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 = MBlaze
|
||||
parent = Target
|
||||
has_asmparser = 1
|
||||
has_asmprinter = 1
|
||||
has_disassembler = 1
|
||||
|
||||
[component_1]
|
||||
type = Library
|
||||
name = MBlazeCodeGen
|
||||
parent = MBlaze
|
||||
required_libraries = AsmPrinter CodeGen Core MBlazeAsmPrinter MBlazeDesc MBlazeInfo MC SelectionDAG Support Target
|
||||
add_to_library_groups = MBlaze
|
@ -1,32 +0,0 @@
|
||||
//===-- MBlaze.h - Top-level interface for MBlaze ---------------*- 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 MBlaze back-end.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TARGET_MBLAZE_H
|
||||
#define TARGET_MBLAZE_H
|
||||
|
||||
#include "MCTargetDesc/MBlazeBaseInfo.h"
|
||||
#include "MCTargetDesc/MBlazeMCTargetDesc.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
namespace llvm {
|
||||
class MBlazeTargetMachine;
|
||||
class FunctionPass;
|
||||
class MachineCodeEmitter;
|
||||
|
||||
FunctionPass *createMBlazeISelDag(MBlazeTargetMachine &TM);
|
||||
FunctionPass *createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &TM);
|
||||
|
||||
} // end namespace llvm;
|
||||
|
||||
#endif
|
@ -1,73 +0,0 @@
|
||||
//===-- MBlaze.td - Describe the MBlaze Target Machine -----*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This is the top level entry point for the MBlaze target.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Target-independent interfaces
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "llvm/Target/Target.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register File, Calling Conv, Instruction Descriptions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "MBlazeRegisterInfo.td"
|
||||
include "MBlazeSchedule.td"
|
||||
include "MBlazeIntrinsics.td"
|
||||
include "MBlazeInstrInfo.td"
|
||||
include "MBlazeCallingConv.td"
|
||||
|
||||
def MBlazeInstrInfo : InstrInfo;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Microblaze Subtarget features //
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def FeatureBarrel : SubtargetFeature<"barrel", "HasBarrel", "true",
|
||||
"Implements barrel shifter">;
|
||||
def FeatureDiv : SubtargetFeature<"div", "HasDiv", "true",
|
||||
"Implements hardware divider">;
|
||||
def FeatureMul : SubtargetFeature<"mul", "HasMul", "true",
|
||||
"Implements hardware multiplier">;
|
||||
def FeaturePatCmp : SubtargetFeature<"patcmp", "HasPatCmp", "true",
|
||||
"Implements pattern compare instruction">;
|
||||
def FeatureFPU : SubtargetFeature<"fpu", "HasFPU", "true",
|
||||
"Implements floating point unit">;
|
||||
def FeatureMul64 : SubtargetFeature<"mul64", "HasMul64", "true",
|
||||
"Implements multiplier with 64-bit result">;
|
||||
def FeatureSqrt : SubtargetFeature<"sqrt", "HasSqrt", "true",
|
||||
"Implements sqrt and floating point convert">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze processors supported.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def : Processor<"mblaze", NoItineraries, []>;
|
||||
def : Processor<"mblaze3", MBlazePipe3Itineraries, []>;
|
||||
def : Processor<"mblaze5", MBlazePipe5Itineraries, []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Descriptions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def MBlazeAsmWriter : AsmWriter {
|
||||
string AsmWriterClassName = "InstPrinter";
|
||||
bit isMCAsmWriter = 1;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Target Declaration
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def MBlaze : Target {
|
||||
let InstructionSet = MBlazeInstrInfo;
|
||||
let AssemblyWriters = [MBlazeAsmWriter];
|
||||
}
|
@ -1,326 +0,0 @@
|
||||
//===-- MBlazeAsmPrinter.cpp - MBlaze 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 GAS-format MBlaze assembly language.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "mblaze-asm-printer"
|
||||
|
||||
#include "MBlaze.h"
|
||||
#include "InstPrinter/MBlazeInstPrinter.h"
|
||||
#include "MBlazeInstrInfo.h"
|
||||
#include "MBlazeMCInstLower.h"
|
||||
#include "MBlazeMachineFunction.h"
|
||||
#include "MBlazeSubtarget.h"
|
||||
#include "MBlazeTargetMachine.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/Mangler.h"
|
||||
#include "llvm/Target/TargetLoweringObjectFile.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <cctype>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class MBlazeAsmPrinter : public AsmPrinter {
|
||||
const MBlazeSubtarget *Subtarget;
|
||||
public:
|
||||
explicit MBlazeAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
||||
: AsmPrinter(TM, Streamer) {
|
||||
Subtarget = &TM.getSubtarget<MBlazeSubtarget>();
|
||||
}
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "MBlaze Assembly Printer";
|
||||
}
|
||||
|
||||
void printSavedRegsBitmask();
|
||||
void emitFrameDirective();
|
||||
virtual void EmitFunctionBodyStart();
|
||||
virtual void EmitFunctionBodyEnd();
|
||||
virtual void EmitFunctionEntryLabel();
|
||||
|
||||
virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB)
|
||||
const;
|
||||
|
||||
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O);
|
||||
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
|
||||
void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O);
|
||||
void printFSLImm(const MachineInstr *MI, int opNum, raw_ostream &O);
|
||||
void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
|
||||
void EmitInstruction(const MachineInstr *MI);
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
// #include "MBlazeGenAsmWriter.inc"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// MBlaze Asm Directives
|
||||
//
|
||||
// -- Frame directive "frame Stackpointer, Stacksize, RARegister"
|
||||
// Describe the stack frame.
|
||||
//
|
||||
// -- Mask directives "mask bitmask, offset"
|
||||
// Tells the assembler which registers are saved and where.
|
||||
// bitmask - contain a little endian bitset indicating which registers are
|
||||
// saved on function prologue (e.g. with a 0x80000000 mask, the
|
||||
// assembler knows the register 31 (RA) is saved at prologue.
|
||||
// offset - the position before stack pointer subtraction indicating where
|
||||
// the first saved register on prologue is located. (e.g. with a
|
||||
//
|
||||
// Consider the following function prologue:
|
||||
//
|
||||
// .frame R19,48,R15
|
||||
// .mask 0xc0000000,-8
|
||||
// addiu R1, R1, -48
|
||||
// sw R15, 40(R1)
|
||||
// sw R19, 36(R1)
|
||||
//
|
||||
// With a 0xc0000000 mask, the assembler knows the register 15 (R15) and
|
||||
// 19 (R19) are saved at prologue. As the save order on prologue is from
|
||||
// left to right, R15 is saved first. A -8 offset means that after the
|
||||
// stack pointer subtration, the first register in the mask (R15) will be
|
||||
// saved at address 48-8=40.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Print a 32 bit hex number with all numbers.
|
||||
static void printHex32(unsigned int Value, raw_ostream &O) {
|
||||
O << "0x";
|
||||
for (int i = 7; i >= 0; i--)
|
||||
O.write_hex((Value & (0xF << (i*4))) >> (i*4));
|
||||
}
|
||||
|
||||
// Create a bitmask with all callee saved registers for CPU or Floating Point
|
||||
// registers. For CPU registers consider RA, GP and FP for saving if necessary.
|
||||
void MBlazeAsmPrinter::printSavedRegsBitmask() {
|
||||
const TargetFrameLowering *TFI = TM.getFrameLowering();
|
||||
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
|
||||
// CPU Saved Registers Bitmasks
|
||||
unsigned int CPUBitmask = 0;
|
||||
|
||||
// Set the CPU Bitmasks
|
||||
const MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
||||
unsigned Reg = CSI[i].getReg();
|
||||
unsigned RegNum = getMBlazeRegisterNumbering(Reg);
|
||||
if (MBlaze::GPRRegClass.contains(Reg))
|
||||
CPUBitmask |= (1 << RegNum);
|
||||
}
|
||||
|
||||
// Return Address and Frame registers must also be set in CPUBitmask.
|
||||
if (TFI->hasFP(*MF))
|
||||
CPUBitmask |= (1 << getMBlazeRegisterNumbering(RI.getFrameRegister(*MF)));
|
||||
|
||||
if (MFI->adjustsStack())
|
||||
CPUBitmask |= (1 << getMBlazeRegisterNumbering(RI.getRARegister()));
|
||||
|
||||
// Print CPUBitmask
|
||||
OutStreamer.EmitRawText("\t.mask\t0x" + Twine::utohexstr(CPUBitmask));
|
||||
}
|
||||
|
||||
/// Frame Directive
|
||||
void MBlazeAsmPrinter::emitFrameDirective() {
|
||||
if (!OutStreamer.hasRawTextSupport())
|
||||
return;
|
||||
|
||||
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
unsigned stkReg = RI.getFrameRegister(*MF);
|
||||
unsigned retReg = RI.getRARegister();
|
||||
unsigned stkSze = MF->getFrameInfo()->getStackSize();
|
||||
|
||||
OutStreamer.EmitRawText("\t.frame\t" +
|
||||
Twine(MBlazeInstPrinter::getRegisterName(stkReg)) +
|
||||
"," + Twine(stkSze) + "," +
|
||||
Twine(MBlazeInstPrinter::getRegisterName(retReg)));
|
||||
}
|
||||
|
||||
void MBlazeAsmPrinter::EmitFunctionEntryLabel() {
|
||||
if (OutStreamer.hasRawTextSupport())
|
||||
OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName()));
|
||||
AsmPrinter::EmitFunctionEntryLabel();
|
||||
}
|
||||
|
||||
void MBlazeAsmPrinter::EmitFunctionBodyStart() {
|
||||
if (!OutStreamer.hasRawTextSupport())
|
||||
return;
|
||||
|
||||
emitFrameDirective();
|
||||
printSavedRegsBitmask();
|
||||
}
|
||||
|
||||
void MBlazeAsmPrinter::EmitFunctionBodyEnd() {
|
||||
if (OutStreamer.hasRawTextSupport())
|
||||
OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName()));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MBlazeMCInstLower MCInstLowering(OutContext, *this);
|
||||
|
||||
MCInst TmpInst;
|
||||
MCInstLowering.Lower(MI, TmpInst);
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
}
|
||||
|
||||
// Print out an operand for an inline asm expression.
|
||||
bool MBlazeAsmPrinter::
|
||||
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] != 0) return true; // Unknown modifier.
|
||||
|
||||
switch (ExtraCode[0]) {
|
||||
default:
|
||||
// See if this is a generic print operand
|
||||
return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
|
||||
}
|
||||
|
||||
printOperand(MI, OpNo, O);
|
||||
return false;
|
||||
}
|
||||
|
||||
void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(opNum);
|
||||
|
||||
switch (MO.getType()) {
|
||||
case MachineOperand::MO_Register:
|
||||
O << MBlazeInstPrinter::getRegisterName(MO.getReg());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_Immediate:
|
||||
O << (int32_t)MO.getImm();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_FPImmediate: {
|
||||
const ConstantFP *fp = MO.getFPImm();
|
||||
printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue(), O);
|
||||
O << ";\t# immediate = " << *fp;
|
||||
break;
|
||||
}
|
||||
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
O << *MO.getMBB()->getSymbol();
|
||||
return;
|
||||
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
O << *Mang->getSymbol(MO.getGlobal());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
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();
|
||||
if (MO.getOffset())
|
||||
O << "+" << MO.getOffset();
|
||||
break;
|
||||
|
||||
default:
|
||||
llvm_unreachable("<unknown operand type>");
|
||||
}
|
||||
}
|
||||
|
||||
void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(opNum);
|
||||
if (MO.isImm())
|
||||
O << (uint32_t)MO.getImm();
|
||||
else
|
||||
printOperand(MI, opNum, O);
|
||||
}
|
||||
|
||||
void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(opNum);
|
||||
if (MO.isImm())
|
||||
O << "rfsl" << (unsigned int)MO.getImm();
|
||||
else
|
||||
printOperand(MI, opNum, O);
|
||||
}
|
||||
|
||||
void MBlazeAsmPrinter::
|
||||
printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
|
||||
const char *Modifier) {
|
||||
printOperand(MI, opNum, O);
|
||||
O << ", ";
|
||||
printOperand(MI, opNum+1, O);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
bool MBlazeAsmPrinter::
|
||||
isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
|
||||
// If this is a landing pad, it isn't a fall through. If it has no preds,
|
||||
// then nothing falls through to it.
|
||||
if (MBB->isLandingPad() || MBB->pred_empty())
|
||||
return false;
|
||||
|
||||
// If there isn't exactly one predecessor, it can't be a fall through.
|
||||
MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI;
|
||||
++PI2;
|
||||
if (PI2 != MBB->pred_end())
|
||||
return false;
|
||||
|
||||
// The predecessor has to be immediately before this block.
|
||||
const MachineBasicBlock *Pred = *PI;
|
||||
|
||||
if (!Pred->isLayoutSuccessor(MBB))
|
||||
return false;
|
||||
|
||||
// If the block is completely empty, then it definitely does fall through.
|
||||
if (Pred->empty())
|
||||
return true;
|
||||
|
||||
// Check if the last terminator is an unconditional branch.
|
||||
MachineBasicBlock::const_iterator I = Pred->end();
|
||||
while (I != Pred->begin() && !(--I)->isTerminator())
|
||||
; // Noop
|
||||
return I == Pred->end() || !I->isBarrier();
|
||||
}
|
||||
|
||||
// Force static initialization.
|
||||
extern "C" void LLVMInitializeMBlazeAsmPrinter() {
|
||||
RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
//===- MBlazeCallingConv.td - Calling Conventions for MBlaze -*- 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 MBlaze architecture.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze ABI Calling Convention
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def RetCC_MBlaze : CallingConv<[
|
||||
// i32 are returned in registers R3, R4
|
||||
CCIfType<[i32,f32], CCAssignToReg<[R3, R4]>>
|
||||
]>;
|
||||
|
||||
def CC_MBlaze : CallingConv<[
|
||||
CCIfType<[i32,f32], CCCustom<"CC_MBlaze_AssignReg">>,
|
||||
CCIfType<[i32,f32], CCAssignToStack<4, 4>>
|
||||
]>;
|
@ -1,252 +0,0 @@
|
||||
//===-- DelaySlotFiller.cpp - MBlaze delay slot filler --------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// A pass that attempts to fill instructions with delay slots. If no
|
||||
// instructions can be moved into the delay slot then a NOP is placed there.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "delay-slot-filler"
|
||||
|
||||
#include "MBlaze.h"
|
||||
#include "MBlazeTargetMachine.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(FilledSlots, "Number of delay slots filled");
|
||||
|
||||
static cl::opt<bool> MBDisableDelaySlotFiller(
|
||||
"disable-mblaze-delay-filler",
|
||||
cl::init(false),
|
||||
cl::desc("Disable the MBlaze delay slot filter."),
|
||||
cl::Hidden);
|
||||
|
||||
namespace {
|
||||
struct Filler : public MachineFunctionPass {
|
||||
TargetMachine &TM;
|
||||
|
||||
static char ID;
|
||||
Filler(TargetMachine &tm)
|
||||
: MachineFunctionPass(ID), TM(tm) { }
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "MBlaze Delay Slot Filler";
|
||||
}
|
||||
|
||||
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
|
||||
bool runOnMachineFunction(MachineFunction &F) {
|
||||
bool Changed = false;
|
||||
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
|
||||
FI != FE; ++FI)
|
||||
Changed |= runOnMachineBasicBlock(*FI);
|
||||
return Changed;
|
||||
}
|
||||
|
||||
};
|
||||
char Filler::ID = 0;
|
||||
} // end of anonymous namespace
|
||||
|
||||
static bool hasImmInstruction(MachineBasicBlock::iterator &candidate) {
|
||||
// Any instruction with an immediate mode operand greater than
|
||||
// 16-bits requires an implicit IMM instruction.
|
||||
unsigned numOper = candidate->getNumOperands();
|
||||
for (unsigned op = 0; op < numOper; ++op) {
|
||||
MachineOperand &mop = candidate->getOperand(op);
|
||||
|
||||
// The operand requires more than 16-bits to represent.
|
||||
if (mop.isImm() && (mop.getImm() < -0x8000 || mop.getImm() > 0x7fff))
|
||||
return true;
|
||||
|
||||
// We must assume that unknown immediate values require more than
|
||||
// 16-bits to represent.
|
||||
if (mop.isGlobal() || mop.isSymbol() || mop.isJTI() || mop.isCPI())
|
||||
return true;
|
||||
|
||||
// FIXME: we could probably check to see if the FP value happens
|
||||
// to not need an IMM instruction. For now we just always
|
||||
// assume that FP values do.
|
||||
if (mop.isFPImm())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static unsigned getLastRealOperand(MachineBasicBlock::iterator &instr) {
|
||||
switch (instr->getOpcode()) {
|
||||
default: return instr->getNumOperands();
|
||||
|
||||
// These instructions have a variable number of operands but the first two
|
||||
// are the "real" operands that we care about during hazard detection.
|
||||
case MBlaze::BRLID:
|
||||
case MBlaze::BRALID:
|
||||
case MBlaze::BRLD:
|
||||
case MBlaze::BRALD:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static bool delayHasHazard(MachineBasicBlock::iterator &candidate,
|
||||
MachineBasicBlock::iterator &slot) {
|
||||
// Hazard check
|
||||
MachineBasicBlock::iterator a = candidate;
|
||||
MachineBasicBlock::iterator b = slot;
|
||||
|
||||
// MBB layout:-
|
||||
// candidate := a0 = operation(a1, a2)
|
||||
// ...middle bit...
|
||||
// slot := b0 = operation(b1, b2)
|
||||
|
||||
// Possible hazards:-/
|
||||
// 1. a1 or a2 was written during the middle bit
|
||||
// 2. a0 was read or written during the middle bit
|
||||
// 3. a0 is one or more of {b0, b1, b2}
|
||||
// 4. b0 is one or more of {a1, a2}
|
||||
// 5. a accesses memory, and the middle bit
|
||||
// contains a store operation.
|
||||
bool a_is_memory = candidate->mayLoad() || candidate->mayStore();
|
||||
|
||||
// Determine the number of operands in the slot instruction and in the
|
||||
// candidate instruction.
|
||||
const unsigned aend = getLastRealOperand(a);
|
||||
const unsigned bend = getLastRealOperand(b);
|
||||
|
||||
// Check hazards type 1, 2 and 5 by scanning the middle bit
|
||||
MachineBasicBlock::iterator m = a;
|
||||
for (++m; m != b; ++m) {
|
||||
for (unsigned aop = 0; aop<aend; ++aop) {
|
||||
bool aop_is_reg = a->getOperand(aop).isReg();
|
||||
if (!aop_is_reg) continue;
|
||||
|
||||
bool aop_is_def = a->getOperand(aop).isDef();
|
||||
unsigned aop_reg = a->getOperand(aop).getReg();
|
||||
|
||||
const unsigned mend = getLastRealOperand(m);
|
||||
for (unsigned mop = 0; mop<mend; ++mop) {
|
||||
bool mop_is_reg = m->getOperand(mop).isReg();
|
||||
if (!mop_is_reg) continue;
|
||||
|
||||
bool mop_is_def = m->getOperand(mop).isDef();
|
||||
unsigned mop_reg = m->getOperand(mop).getReg();
|
||||
|
||||
if (aop_is_def && (mop_reg == aop_reg))
|
||||
return true; // Hazard type 2, because aop = a0
|
||||
else if (mop_is_def && (mop_reg == aop_reg))
|
||||
return true; // Hazard type 1, because aop in {a1, a2}
|
||||
}
|
||||
}
|
||||
|
||||
// Check hazard type 5
|
||||
if (a_is_memory && m->mayStore())
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check hazard type 3 & 4
|
||||
for (unsigned aop = 0; aop<aend; ++aop) {
|
||||
if (a->getOperand(aop).isReg()) {
|
||||
unsigned aop_reg = a->getOperand(aop).getReg();
|
||||
|
||||
for (unsigned bop = 0; bop<bend; ++bop) {
|
||||
if (b->getOperand(bop).isReg() && !b->getOperand(bop).isImplicit()) {
|
||||
unsigned bop_reg = b->getOperand(bop).getReg();
|
||||
if (aop_reg == bop_reg)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isDelayFiller(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator candidate) {
|
||||
if (candidate == MBB.begin())
|
||||
return false;
|
||||
|
||||
--candidate;
|
||||
return (candidate->hasDelaySlot());
|
||||
}
|
||||
|
||||
static bool hasUnknownSideEffects(MachineBasicBlock::iterator &I) {
|
||||
if (!I->hasUnmodeledSideEffects())
|
||||
return false;
|
||||
|
||||
unsigned op = I->getOpcode();
|
||||
if (op == MBlaze::ADDK || op == MBlaze::ADDIK ||
|
||||
op == MBlaze::ADDC || op == MBlaze::ADDIC ||
|
||||
op == MBlaze::ADDKC || op == MBlaze::ADDIKC ||
|
||||
op == MBlaze::RSUBK || op == MBlaze::RSUBIK ||
|
||||
op == MBlaze::RSUBC || op == MBlaze::RSUBIC ||
|
||||
op == MBlaze::RSUBKC || op == MBlaze::RSUBIKC)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static MachineBasicBlock::iterator
|
||||
findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator slot) {
|
||||
MachineBasicBlock::iterator I = slot;
|
||||
while (true) {
|
||||
if (I == MBB.begin())
|
||||
break;
|
||||
|
||||
--I;
|
||||
if (I->hasDelaySlot() || I->isBranch() || isDelayFiller(MBB,I) ||
|
||||
I->isCall() || I->isReturn() || I->isBarrier() ||
|
||||
hasUnknownSideEffects(I))
|
||||
break;
|
||||
|
||||
if (hasImmInstruction(I) || delayHasHazard(I,slot))
|
||||
continue;
|
||||
|
||||
return I;
|
||||
}
|
||||
|
||||
return MBB.end();
|
||||
}
|
||||
|
||||
/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
|
||||
/// Currently, we fill delay slots with NOPs. We assume there is only one
|
||||
/// delay slot per delayed instruction.
|
||||
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
|
||||
bool Changed = false;
|
||||
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I)
|
||||
if (I->hasDelaySlot()) {
|
||||
MachineBasicBlock::iterator D = MBB.end();
|
||||
MachineBasicBlock::iterator J = I;
|
||||
|
||||
if (!MBDisableDelaySlotFiller)
|
||||
D = findDelayInstr(MBB,I);
|
||||
|
||||
++FilledSlots;
|
||||
Changed = true;
|
||||
|
||||
if (D == MBB.end())
|
||||
BuildMI(MBB, ++J, I->getDebugLoc(),TM.getInstrInfo()->get(MBlaze::NOP));
|
||||
else
|
||||
MBB.splice(++J, &MBB, D);
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
|
||||
/// createMBlazeDelaySlotFillerPass - Returns a pass that fills in delay
|
||||
/// slots in MBlaze MachineFunctions
|
||||
FunctionPass *llvm::createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &tm) {
|
||||
return new Filler(tm);
|
||||
}
|
||||
|
@ -1,488 +0,0 @@
|
||||
//===-- MBlazeFrameLowering.cpp - MBlaze 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 MBlaze implementation of TargetFrameLowering class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "mblaze-frame-lowering"
|
||||
|
||||
#include "MBlazeFrameLowering.h"
|
||||
#include "InstPrinter/MBlazeInstPrinter.h"
|
||||
#include "MBlazeInstrInfo.h"
|
||||
#include "MBlazeMachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool> MBDisableStackAdjust(
|
||||
"disable-mblaze-stack-adjust",
|
||||
cl::init(false),
|
||||
cl::desc("Disable MBlaze stack layout adjustment."),
|
||||
cl::Hidden);
|
||||
|
||||
static void replaceFrameIndexes(MachineFunction &MF,
|
||||
SmallVectorImpl<std::pair<int,int64_t> > &FR) {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
const SmallVectorImpl<std::pair<int,int64_t> >::iterator FRB = FR.begin();
|
||||
const SmallVectorImpl<std::pair<int,int64_t> >::iterator FRE = FR.end();
|
||||
|
||||
SmallVectorImpl<std::pair<int,int64_t> >::iterator FRI = FRB;
|
||||
for (; FRI != FRE; ++FRI) {
|
||||
MFI->RemoveStackObject(FRI->first);
|
||||
int NFI = MFI->CreateFixedObject(4, FRI->second, true);
|
||||
MBlazeFI->recordReplacement(FRI->first, NFI);
|
||||
|
||||
for (MachineFunction::iterator MB=MF.begin(), ME=MF.end(); MB!=ME; ++MB) {
|
||||
MachineBasicBlock::iterator MBB = MB->begin();
|
||||
const MachineBasicBlock::iterator MBE = MB->end();
|
||||
|
||||
for (; MBB != MBE; ++MBB) {
|
||||
MachineInstr::mop_iterator MIB = MBB->operands_begin();
|
||||
const MachineInstr::mop_iterator MIE = MBB->operands_end();
|
||||
|
||||
for (MachineInstr::mop_iterator MII = MIB; MII != MIE; ++MII) {
|
||||
if (!MII->isFI() || MII->getIndex() != FRI->first) continue;
|
||||
DEBUG(dbgs() << "FOUND FI#" << MII->getIndex() << "\n");
|
||||
MII->setIndex(NFI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Stack Frame Processing methods
|
||||
// +----------------------------+
|
||||
//
|
||||
// The stack is allocated decrementing the stack pointer on
|
||||
// the first instruction of a function prologue. Once decremented,
|
||||
// all stack references are are done through a positive offset
|
||||
// from the stack/frame pointer, so the stack is considered
|
||||
// to grow up.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void analyzeFrameIndexes(MachineFunction &MF) {
|
||||
if (MBDisableStackAdjust) return;
|
||||
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
const MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
|
||||
MachineRegisterInfo::livein_iterator LII = MRI.livein_begin();
|
||||
MachineRegisterInfo::livein_iterator LIE = MRI.livein_end();
|
||||
const SmallVectorImpl<int> &LiveInFI = MBlazeFI->getLiveIn();
|
||||
SmallVector<MachineInstr*, 16> EraseInstr;
|
||||
SmallVector<std::pair<int,int64_t>, 16> FrameRelocate;
|
||||
|
||||
MachineBasicBlock *MBB = MF.getBlockNumbered(0);
|
||||
MachineBasicBlock::iterator MIB = MBB->begin();
|
||||
MachineBasicBlock::iterator MIE = MBB->end();
|
||||
|
||||
int StackAdjust = 0;
|
||||
int StackOffset = -28;
|
||||
|
||||
// In this loop we are searching frame indexes that corrospond to incoming
|
||||
// arguments that are already in the stack. We look for instruction sequences
|
||||
// like the following:
|
||||
//
|
||||
// LWI REG, FI1, 0
|
||||
// ...
|
||||
// SWI REG, FI2, 0
|
||||
//
|
||||
// As long as there are no defs of REG in the ... part, we can eliminate
|
||||
// the SWI instruction because the value has already been stored to the
|
||||
// stack by the caller. All we need to do is locate FI at the correct
|
||||
// stack location according to the calling convensions.
|
||||
//
|
||||
// Additionally, if the SWI operation kills the def of REG then we don't
|
||||
// need the LWI operation so we can erase it as well.
|
||||
for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) {
|
||||
for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) {
|
||||
if (I->getOpcode() != MBlaze::LWI || I->getNumOperands() != 3 ||
|
||||
!I->getOperand(1).isFI() || !I->getOperand(0).isReg() ||
|
||||
I->getOperand(1).getIndex() != LiveInFI[i]) continue;
|
||||
|
||||
unsigned FIReg = I->getOperand(0).getReg();
|
||||
MachineBasicBlock::iterator SI = I;
|
||||
for (SI++; SI != MIE; ++SI) {
|
||||
if (!SI->getOperand(0).isReg() ||
|
||||
!SI->getOperand(1).isFI() ||
|
||||
SI->getOpcode() != MBlaze::SWI) continue;
|
||||
|
||||
int FI = SI->getOperand(1).getIndex();
|
||||
if (SI->getOperand(0).getReg() != FIReg ||
|
||||
MFI->isFixedObjectIndex(FI) ||
|
||||
MFI->getObjectSize(FI) != 4) continue;
|
||||
|
||||
if (SI->getOperand(0).isDef()) break;
|
||||
|
||||
if (SI->getOperand(0).isKill()) {
|
||||
DEBUG(dbgs() << "LWI for FI#" << I->getOperand(1).getIndex()
|
||||
<< " removed\n");
|
||||
EraseInstr.push_back(I);
|
||||
}
|
||||
|
||||
EraseInstr.push_back(SI);
|
||||
DEBUG(dbgs() << "SWI for FI#" << FI << " removed\n");
|
||||
|
||||
FrameRelocate.push_back(std::make_pair(FI,StackOffset));
|
||||
DEBUG(dbgs() << "FI#" << FI << " relocated to " << StackOffset << "\n");
|
||||
|
||||
StackOffset -= 4;
|
||||
StackAdjust += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In this loop we are searching for frame indexes that corrospond to
|
||||
// incoming arguments that are in registers. We look for instruction
|
||||
// sequences like the following:
|
||||
//
|
||||
// ... SWI REG, FI, 0
|
||||
//
|
||||
// As long as the ... part does not define REG and if REG is an incoming
|
||||
// parameter register then we know that, according to ABI convensions, the
|
||||
// caller has allocated stack space for it already. Instead of allocating
|
||||
// stack space on our frame, we record the correct location in the callers
|
||||
// frame.
|
||||
for (MachineRegisterInfo::livein_iterator LI = LII; LI != LIE; ++LI) {
|
||||
for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) {
|
||||
if (I->definesRegister(LI->first))
|
||||
break;
|
||||
|
||||
if (I->getOpcode() != MBlaze::SWI || I->getNumOperands() != 3 ||
|
||||
!I->getOperand(1).isFI() || !I->getOperand(0).isReg() ||
|
||||
I->getOperand(1).getIndex() < 0) continue;
|
||||
|
||||
if (I->getOperand(0).getReg() == LI->first) {
|
||||
int FI = I->getOperand(1).getIndex();
|
||||
MBlazeFI->recordLiveIn(FI);
|
||||
|
||||
int FILoc = 0;
|
||||
switch (LI->first) {
|
||||
default: llvm_unreachable("invalid incoming parameter!");
|
||||
case MBlaze::R5: FILoc = -4; break;
|
||||
case MBlaze::R6: FILoc = -8; break;
|
||||
case MBlaze::R7: FILoc = -12; break;
|
||||
case MBlaze::R8: FILoc = -16; break;
|
||||
case MBlaze::R9: FILoc = -20; break;
|
||||
case MBlaze::R10: FILoc = -24; break;
|
||||
}
|
||||
|
||||
StackAdjust += 4;
|
||||
FrameRelocate.push_back(std::make_pair(FI,FILoc));
|
||||
DEBUG(dbgs() << "FI#" << FI << " relocated to " << FILoc << "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go ahead and erase all of the instructions that we determined were
|
||||
// no longer needed.
|
||||
for (int i = 0, e = EraseInstr.size(); i < e; ++i)
|
||||
MBB->erase(EraseInstr[i]);
|
||||
|
||||
// Replace all of the frame indexes that we have relocated with new
|
||||
// fixed object frame indexes.
|
||||
replaceFrameIndexes(MF, FrameRelocate);
|
||||
}
|
||||
|
||||
static void interruptFrameLayout(MachineFunction &MF) {
|
||||
const Function *F = MF.getFunction();
|
||||
CallingConv::ID CallConv = F->getCallingConv();
|
||||
|
||||
// If this function is not using either the interrupt_handler
|
||||
// calling convention or the save_volatiles calling convention
|
||||
// then we don't need to do any additional frame layout.
|
||||
if (CallConv != CallingConv::MBLAZE_INTR &&
|
||||
CallConv != CallingConv::MBLAZE_SVOL)
|
||||
return;
|
||||
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
const MBlazeInstrInfo &TII =
|
||||
*static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||
|
||||
// Determine if the calling convention is the interrupt_handler
|
||||
// calling convention. Some pieces of the prologue and epilogue
|
||||
// only need to be emitted if we are lowering and interrupt handler.
|
||||
bool isIntr = CallConv == CallingConv::MBLAZE_INTR;
|
||||
|
||||
// Determine where to put prologue and epilogue additions
|
||||
MachineBasicBlock &MENT = MF.front();
|
||||
MachineBasicBlock &MEXT = MF.back();
|
||||
|
||||
MachineBasicBlock::iterator MENTI = MENT.begin();
|
||||
MachineBasicBlock::iterator MEXTI = prior(MEXT.end());
|
||||
|
||||
DebugLoc ENTDL = MENTI != MENT.end() ? MENTI->getDebugLoc() : DebugLoc();
|
||||
DebugLoc EXTDL = MEXTI != MEXT.end() ? MEXTI->getDebugLoc() : DebugLoc();
|
||||
|
||||
// Store the frame indexes generated during prologue additions for use
|
||||
// when we are generating the epilogue additions.
|
||||
SmallVector<int, 10> VFI;
|
||||
|
||||
// Build the prologue SWI for R3 - R12 if needed. Note that R11 must
|
||||
// always have a SWI because it is used when processing RMSR.
|
||||
for (unsigned r = MBlaze::R3; r <= MBlaze::R12; ++r) {
|
||||
if (!MRI.isPhysRegUsed(r) && !(isIntr && r == MBlaze::R11)) continue;
|
||||
|
||||
int FI = MFI->CreateStackObject(4,4,false,false);
|
||||
VFI.push_back(FI);
|
||||
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), r)
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
}
|
||||
|
||||
// Build the prologue SWI for R17, R18
|
||||
int R17FI = MFI->CreateStackObject(4,4,false,false);
|
||||
int R18FI = MFI->CreateStackObject(4,4,false,false);
|
||||
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R17)
|
||||
.addFrameIndex(R17FI).addImm(0);
|
||||
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R18)
|
||||
.addFrameIndex(R18FI).addImm(0);
|
||||
|
||||
// Buid the prologue SWI and the epilogue LWI for RMSR if needed
|
||||
if (isIntr) {
|
||||
int MSRFI = MFI->CreateStackObject(4,4,false,false);
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::MFS), MBlaze::R11)
|
||||
.addReg(MBlaze::RMSR);
|
||||
BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R11)
|
||||
.addFrameIndex(MSRFI).addImm(0);
|
||||
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R11)
|
||||
.addFrameIndex(MSRFI).addImm(0);
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::MTS), MBlaze::RMSR)
|
||||
.addReg(MBlaze::R11);
|
||||
}
|
||||
|
||||
// Build the epilogue LWI for R17, R18
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R18)
|
||||
.addFrameIndex(R18FI).addImm(0);
|
||||
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R17)
|
||||
.addFrameIndex(R17FI).addImm(0);
|
||||
|
||||
// Build the epilogue LWI for R3 - R12 if needed
|
||||
for (unsigned r = MBlaze::R12, i = VFI.size(); r >= MBlaze::R3; --r) {
|
||||
if (!MRI.isPhysRegUsed(r)) continue;
|
||||
BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), r)
|
||||
.addFrameIndex(VFI[--i]).addImm(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void determineFrameLayout(MachineFunction &MF) {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
|
||||
// Replace the dummy '0' SPOffset by the negative offsets, as explained on
|
||||
// LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid
|
||||
// the approach done by calculateFrameObjectOffsets to the stack frame.
|
||||
MBlazeFI->adjustLoadArgsFI(MFI);
|
||||
MBlazeFI->adjustStoreVarArgsFI(MFI);
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo
|
||||
unsigned FrameSize = MFI->getStackSize();
|
||||
DEBUG(dbgs() << "Original Frame Size: " << FrameSize << "\n" );
|
||||
|
||||
// Get the alignments provided by the target, and the maximum alignment
|
||||
// (if any) of the fixed frame objects.
|
||||
// unsigned MaxAlign = MFI->getMaxAlignment();
|
||||
unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
|
||||
unsigned AlignMask = TargetAlign - 1;
|
||||
|
||||
// Make sure the frame is aligned.
|
||||
FrameSize = (FrameSize + AlignMask) & ~AlignMask;
|
||||
MFI->setStackSize(FrameSize);
|
||||
DEBUG(dbgs() << "Aligned Frame Size: " << FrameSize << "\n" );
|
||||
}
|
||||
|
||||
int MBlazeFrameLowering::getFrameIndexOffset(const MachineFunction &MF, int FI)
|
||||
const {
|
||||
const MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
if (MBlazeFI->hasReplacement(FI))
|
||||
FI = MBlazeFI->getReplacement(FI);
|
||||
return TargetFrameLowering::getFrameIndexOffset(MF,FI);
|
||||
}
|
||||
|
||||
// hasFP - Return true if the specified function should have a dedicated frame
|
||||
// pointer register. This is true if the function has variable sized allocas or
|
||||
// if frame pointer elimination is disabled.
|
||||
bool MBlazeFrameLowering::hasFP(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
|
||||
MFI->hasVarSizedObjects();
|
||||
}
|
||||
|
||||
void MBlazeFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
MachineBasicBlock &MBB = MF.front();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const MBlazeInstrInfo &TII =
|
||||
*static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||
|
||||
CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
|
||||
bool requiresRA = CallConv == CallingConv::MBLAZE_INTR;
|
||||
|
||||
// Determine the correct frame layout
|
||||
determineFrameLayout(MF);
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo.
|
||||
unsigned StackSize = MFI->getStackSize();
|
||||
|
||||
// No need to allocate space on the stack.
|
||||
if (StackSize == 0 && !MFI->adjustsStack() && !requiresRA) return;
|
||||
|
||||
int FPOffset = MBlazeFI->getFPStackOffset();
|
||||
int RAOffset = MBlazeFI->getRAStackOffset();
|
||||
|
||||
// Adjust stack : addi R1, R1, -imm
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDIK), MBlaze::R1)
|
||||
.addReg(MBlaze::R1).addImm(-StackSize);
|
||||
|
||||
// swi R15, R1, stack_loc
|
||||
if (MFI->adjustsStack() || requiresRA) {
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
|
||||
.addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset);
|
||||
}
|
||||
|
||||
if (hasFP(MF)) {
|
||||
// swi R19, R1, stack_loc
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
|
||||
.addReg(MBlaze::R19).addReg(MBlaze::R1).addImm(FPOffset);
|
||||
|
||||
// add R19, R1, R0
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19)
|
||||
.addReg(MBlaze::R1).addReg(MBlaze::R0);
|
||||
}
|
||||
}
|
||||
|
||||
void MBlazeFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
const MBlazeInstrInfo &TII =
|
||||
*static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||
|
||||
DebugLoc dl = MBBI->getDebugLoc();
|
||||
|
||||
CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
|
||||
bool requiresRA = CallConv == CallingConv::MBLAZE_INTR;
|
||||
|
||||
// Get the FI's where RA and FP are saved.
|
||||
int FPOffset = MBlazeFI->getFPStackOffset();
|
||||
int RAOffset = MBlazeFI->getRAStackOffset();
|
||||
|
||||
if (hasFP(MF)) {
|
||||
// add R1, R19, R0
|
||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1)
|
||||
.addReg(MBlaze::R19).addReg(MBlaze::R0);
|
||||
|
||||
// lwi R19, R1, stack_loc
|
||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19)
|
||||
.addReg(MBlaze::R1).addImm(FPOffset);
|
||||
}
|
||||
|
||||
// lwi R15, R1, stack_loc
|
||||
if (MFI->adjustsStack() || requiresRA) {
|
||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15)
|
||||
.addReg(MBlaze::R1).addImm(RAOffset);
|
||||
}
|
||||
|
||||
// Get the number of bytes from FrameInfo
|
||||
int StackSize = (int) MFI->getStackSize();
|
||||
|
||||
// addi R1, R1, imm
|
||||
if (StackSize) {
|
||||
BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDIK), MBlaze::R1)
|
||||
.addReg(MBlaze::R1).addImm(StackSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Eliminate ADJCALLSTACKDOWN/ADJCALLSTACKUP pseudo instructions
|
||||
void MBlazeFrameLowering::
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const {
|
||||
const MBlazeInstrInfo &TII =
|
||||
*static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
|
||||
if (!hasReservedCallFrame(MF)) {
|
||||
// If we have a frame pointer, turn the adjcallstackup instruction into a
|
||||
// 'addi r1, r1, -<amt>' and the adjcallstackdown instruction into
|
||||
// 'addi r1, r1, <amt>'
|
||||
MachineInstr *Old = I;
|
||||
int Amount = Old->getOperand(0).getImm() + 4;
|
||||
if (Amount != 0) {
|
||||
// We need to keep the stack aligned properly. To do this, we round the
|
||||
// amount of space needed for the outgoing arguments up to the next
|
||||
// alignment boundary.
|
||||
unsigned Align = getStackAlignment();
|
||||
Amount = (Amount+Align-1)/Align*Align;
|
||||
|
||||
MachineInstr *New;
|
||||
if (Old->getOpcode() == MBlaze::ADJCALLSTACKDOWN) {
|
||||
New = BuildMI(MF,Old->getDebugLoc(), TII.get(MBlaze::ADDIK),MBlaze::R1)
|
||||
.addReg(MBlaze::R1).addImm(-Amount);
|
||||
} else {
|
||||
assert(Old->getOpcode() == MBlaze::ADJCALLSTACKUP);
|
||||
New = BuildMI(MF,Old->getDebugLoc(), TII.get(MBlaze::ADDIK),MBlaze::R1)
|
||||
.addReg(MBlaze::R1).addImm(Amount);
|
||||
}
|
||||
|
||||
// Replace the pseudo instruction with a new instruction...
|
||||
MBB.insert(I, New);
|
||||
}
|
||||
}
|
||||
|
||||
// Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
|
||||
MBB.erase(I);
|
||||
}
|
||||
|
||||
|
||||
void MBlazeFrameLowering::
|
||||
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
RegScavenger *RS) const {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
|
||||
bool requiresRA = CallConv == CallingConv::MBLAZE_INTR;
|
||||
|
||||
if (MFI->adjustsStack() || requiresRA) {
|
||||
MBlazeFI->setRAStackOffset(0);
|
||||
MFI->CreateFixedObject(4,0,true);
|
||||
}
|
||||
|
||||
if (hasFP(MF)) {
|
||||
MBlazeFI->setFPStackOffset(4);
|
||||
MFI->CreateFixedObject(4,4,true);
|
||||
}
|
||||
|
||||
interruptFrameLayout(MF);
|
||||
analyzeFrameIndexes(MF);
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
//=- MBlazeFrameLowering.h - Define frame lowering for MicroBlaze -*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZE_FRAMEINFO_H
|
||||
#define MBLAZE_FRAMEINFO_H
|
||||
|
||||
#include "MBlaze.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
class MBlazeSubtarget;
|
||||
|
||||
class MBlazeFrameLowering : public TargetFrameLowering {
|
||||
protected:
|
||||
const MBlazeSubtarget &STI;
|
||||
|
||||
public:
|
||||
explicit MBlazeFrameLowering(const MBlazeSubtarget &sti)
|
||||
: TargetFrameLowering(TargetFrameLowering::StackGrowsUp, 4, 0), STI(sti) {
|
||||
}
|
||||
|
||||
/// targetHandlesStackFrameRounding - Returns true if the target is
|
||||
/// responsible for rounding up the stack frame (probably at emitPrologue
|
||||
/// time).
|
||||
bool targetHandlesStackFrameRounding() const { return true; }
|
||||
|
||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||
/// the function.
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
void eliminateCallFramePseudoInstr(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const;
|
||||
|
||||
bool hasFP(const MachineFunction &MF) const;
|
||||
|
||||
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
||||
|
||||
virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
RegScavenger *RS) const;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -1,278 +0,0 @@
|
||||
//===-- MBlazeISelDAGToDAG.cpp - A dag to dag inst selector for MBlaze ----===//
|
||||
//
|
||||
// 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 MBlaze target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "mblaze-isel"
|
||||
#include "MBlaze.h"
|
||||
#include "MBlazeMachineFunction.h"
|
||||
#include "MBlazeRegisterInfo.h"
|
||||
#include "MBlazeSubtarget.h"
|
||||
#include "MBlazeTargetMachine.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/GlobalValue.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Selector Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlazeDAGToDAGISel - MBlaze specific code to select MBlaze machine
|
||||
// instructions for SelectionDAG operations.
|
||||
//===----------------------------------------------------------------------===//
|
||||
namespace {
|
||||
|
||||
class MBlazeDAGToDAGISel : public SelectionDAGISel {
|
||||
|
||||
/// TM - Keep a reference to MBlazeTargetMachine.
|
||||
MBlazeTargetMachine &TM;
|
||||
|
||||
/// Subtarget - Keep a pointer to the MBlazeSubtarget around so that we can
|
||||
/// make the right decision when generating code for different targets.
|
||||
const MBlazeSubtarget &Subtarget;
|
||||
|
||||
public:
|
||||
explicit MBlazeDAGToDAGISel(MBlazeTargetMachine &tm) :
|
||||
SelectionDAGISel(tm),
|
||||
TM(tm), Subtarget(tm.getSubtarget<MBlazeSubtarget>()) {}
|
||||
|
||||
// Pass Name
|
||||
virtual const char *getPassName() const {
|
||||
return "MBlaze DAG->DAG Pattern Instruction Selection";
|
||||
}
|
||||
private:
|
||||
// Include the pieces autogenerated from the target description.
|
||||
#include "MBlazeGenDAGISel.inc"
|
||||
|
||||
/// getTargetMachine - Return a reference to the TargetMachine, casted
|
||||
/// to the target-specific type.
|
||||
const MBlazeTargetMachine &getTargetMachine() {
|
||||
return static_cast<const MBlazeTargetMachine &>(TM);
|
||||
}
|
||||
|
||||
/// getInstrInfo - Return a reference to the TargetInstrInfo, casted
|
||||
/// to the target-specific type.
|
||||
const MBlazeInstrInfo *getInstrInfo() {
|
||||
return getTargetMachine().getInstrInfo();
|
||||
}
|
||||
|
||||
SDNode *getGlobalBaseReg();
|
||||
SDNode *Select(SDNode *N);
|
||||
|
||||
// Address Selection
|
||||
bool SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index);
|
||||
bool SelectAddrRegImm(SDValue N, SDValue &Disp, SDValue &Base);
|
||||
|
||||
// getI32Imm - Return a target constant with the specified value, of type i32.
|
||||
inline SDValue getI32Imm(unsigned Imm) {
|
||||
return CurDAG->getTargetConstant(Imm, MVT::i32);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// isIntS32Immediate - This method tests to see if the node is either a 32-bit
|
||||
/// or 64-bit immediate, and if the value can be accurately represented as a
|
||||
/// sign extension from a 32-bit value. If so, this returns true and the
|
||||
/// immediate.
|
||||
static bool isIntS32Immediate(SDNode *N, int32_t &Imm) {
|
||||
unsigned Opc = N->getOpcode();
|
||||
if (Opc != ISD::Constant)
|
||||
return false;
|
||||
|
||||
Imm = (int32_t)cast<ConstantSDNode>(N)->getZExtValue();
|
||||
if (N->getValueType(0) == MVT::i32)
|
||||
return Imm == (int32_t)cast<ConstantSDNode>(N)->getZExtValue();
|
||||
else
|
||||
return Imm == (int64_t)cast<ConstantSDNode>(N)->getZExtValue();
|
||||
}
|
||||
|
||||
static bool isIntS32Immediate(SDValue Op, int32_t &Imm) {
|
||||
return isIntS32Immediate(Op.getNode(), Imm);
|
||||
}
|
||||
|
||||
|
||||
/// SelectAddressRegReg - Given the specified addressed, check to see if it
|
||||
/// can be represented as an indexed [r+r] operation. Returns false if it
|
||||
/// can be more efficiently represented with [r+imm].
|
||||
bool MBlazeDAGToDAGISel::
|
||||
SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index) {
|
||||
if (N.getOpcode() == ISD::FrameIndex) return false;
|
||||
if (N.getOpcode() == ISD::TargetExternalSymbol ||
|
||||
N.getOpcode() == ISD::TargetGlobalAddress)
|
||||
return false; // direct calls.
|
||||
|
||||
int32_t imm = 0;
|
||||
if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
|
||||
if (isIntS32Immediate(N.getOperand(1), imm))
|
||||
return false; // r+i
|
||||
|
||||
if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable ||
|
||||
N.getOperand(1).getOpcode() == ISD::TargetJumpTable)
|
||||
return false; // jump tables.
|
||||
|
||||
Base = N.getOperand(0);
|
||||
Index = N.getOperand(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns true if the address N can be represented by a base register plus
|
||||
/// a signed 32-bit displacement [r+imm], and if it is not better
|
||||
/// represented as reg+reg.
|
||||
bool MBlazeDAGToDAGISel::
|
||||
SelectAddrRegImm(SDValue N, SDValue &Base, SDValue &Disp) {
|
||||
// If this can be more profitably realized as r+r, fail.
|
||||
if (SelectAddrRegReg(N, Base, Disp))
|
||||
return false;
|
||||
|
||||
if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
|
||||
int32_t imm = 0;
|
||||
if (isIntS32Immediate(N.getOperand(1), imm)) {
|
||||
Disp = CurDAG->getTargetConstant(imm, MVT::i32);
|
||||
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
|
||||
Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
|
||||
} else {
|
||||
Base = N.getOperand(0);
|
||||
}
|
||||
return true; // [r+i]
|
||||
}
|
||||
} else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
|
||||
// Loading from a constant address.
|
||||
uint32_t Imm = CN->getZExtValue();
|
||||
Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0));
|
||||
Base = CurDAG->getRegister(MBlaze::R0, CN->getValueType(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
Disp = CurDAG->getTargetConstant(0, TM.getTargetLowering()->getPointerTy());
|
||||
if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N))
|
||||
Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
|
||||
else
|
||||
Base = N;
|
||||
return true; // [r+0]
|
||||
}
|
||||
|
||||
/// getGlobalBaseReg - Output the instructions required to put the
|
||||
/// GOT address into a register.
|
||||
SDNode *MBlazeDAGToDAGISel::getGlobalBaseReg() {
|
||||
unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
|
||||
return CurDAG->getRegister(GlobalBaseReg,
|
||||
getTargetLowering()->getPointerTy()).getNode();
|
||||
}
|
||||
|
||||
/// Select instructions not customized! Used for
|
||||
/// expanded, promoted and normal instructions
|
||||
SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) {
|
||||
unsigned Opcode = Node->getOpcode();
|
||||
SDLoc dl(Node);
|
||||
|
||||
// If we have a custom node, we already have selected!
|
||||
if (Node->isMachineOpcode())
|
||||
return NULL;
|
||||
|
||||
///
|
||||
// Instruction Selection not handled by the auto-generated
|
||||
// tablegen selection should be handled here.
|
||||
///
|
||||
switch (Opcode) {
|
||||
default: break;
|
||||
|
||||
// Get target GOT address.
|
||||
case ISD::GLOBAL_OFFSET_TABLE:
|
||||
return getGlobalBaseReg();
|
||||
|
||||
case ISD::FrameIndex: {
|
||||
SDValue imm = CurDAG->getTargetConstant(0, MVT::i32);
|
||||
int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
|
||||
EVT VT = Node->getValueType(0);
|
||||
SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
|
||||
unsigned Opc = MBlaze::ADDIK;
|
||||
if (Node->hasOneUse())
|
||||
return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm);
|
||||
return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm);
|
||||
}
|
||||
|
||||
|
||||
/// Handle direct and indirect calls when using PIC. On PIC, when
|
||||
/// GOT is smaller than about 64k (small code) the GA target is
|
||||
/// loaded with only one instruction. Otherwise GA's target must
|
||||
/// be loaded with 3 instructions.
|
||||
case MBlazeISD::JmpLink: {
|
||||
if (TM.getRelocationModel() == Reloc::PIC_) {
|
||||
SDValue Chain = Node->getOperand(0);
|
||||
SDValue Callee = Node->getOperand(1);
|
||||
SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32);
|
||||
SDValue InFlag(0, 0);
|
||||
|
||||
if ((isa<GlobalAddressSDNode>(Callee)) ||
|
||||
(isa<ExternalSymbolSDNode>(Callee)))
|
||||
{
|
||||
/// Direct call for global addresses and external symbols
|
||||
SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32);
|
||||
|
||||
// Use load to get GOT target
|
||||
SDValue Ops[] = { Callee, GPReg, Chain };
|
||||
SDValue Load = SDValue(CurDAG->getMachineNode(MBlaze::LW, dl,
|
||||
MVT::i32, MVT::Other, Ops), 0);
|
||||
Chain = Load.getValue(1);
|
||||
|
||||
// Call target must be on T9
|
||||
Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag);
|
||||
} else
|
||||
/// Indirect call
|
||||
Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag);
|
||||
|
||||
// Emit Jump and Link Register
|
||||
SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other,
|
||||
MVT::Glue, R20Reg, Chain);
|
||||
Chain = SDValue(ResNode, 0);
|
||||
InFlag = SDValue(ResNode, 1);
|
||||
ReplaceUses(SDValue(Node, 0), Chain);
|
||||
ReplaceUses(SDValue(Node, 1), InFlag);
|
||||
return ResNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select the default instruction
|
||||
SDNode *ResNode = SelectCode(Node);
|
||||
|
||||
DEBUG(errs() << "=> ");
|
||||
if (ResNode == NULL || ResNode == Node)
|
||||
DEBUG(Node->dump(CurDAG));
|
||||
else
|
||||
DEBUG(ResNode->dump(CurDAG));
|
||||
DEBUG(errs() << "\n");
|
||||
return ResNode;
|
||||
}
|
||||
|
||||
/// createMBlazeISelDag - This pass converts a legalized DAG into a
|
||||
/// MBlaze-specific DAG, ready for instruction scheduling.
|
||||
FunctionPass *llvm::createMBlazeISelDag(MBlazeTargetMachine &TM) {
|
||||
return new MBlazeDAGToDAGISel(TM);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,179 +0,0 @@
|
||||
//===-- MBlazeISelLowering.h - MBlaze 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 MBlaze uses to lower LLVM code into a
|
||||
// selection DAG.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBlazeISELLOWERING_H
|
||||
#define MBlazeISELLOWERING_H
|
||||
|
||||
#include "MBlaze.h"
|
||||
#include "MBlazeSubtarget.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace MBlazeCC {
|
||||
enum CC {
|
||||
FIRST = 0,
|
||||
EQ,
|
||||
NE,
|
||||
GT,
|
||||
LT,
|
||||
GE,
|
||||
LE
|
||||
};
|
||||
|
||||
inline static CC getOppositeCondition(CC cc) {
|
||||
switch (cc) {
|
||||
default: llvm_unreachable("Unknown condition code");
|
||||
case EQ: return NE;
|
||||
case NE: return EQ;
|
||||
case GT: return LE;
|
||||
case LT: return GE;
|
||||
case GE: return LT;
|
||||
case LE: return GE;
|
||||
}
|
||||
}
|
||||
|
||||
inline static const char *MBlazeCCToString(CC cc) {
|
||||
switch (cc) {
|
||||
default: llvm_unreachable("Unknown condition code");
|
||||
case EQ: return "eq";
|
||||
case NE: return "ne";
|
||||
case GT: return "gt";
|
||||
case LT: return "lt";
|
||||
case GE: return "ge";
|
||||
case LE: return "le";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace MBlazeISD {
|
||||
enum NodeType {
|
||||
// Start the numbering from where ISD NodeType finishes.
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
||||
|
||||
// Jump and link (call)
|
||||
JmpLink,
|
||||
|
||||
// Handle gp_rel (small data/bss sections) relocation.
|
||||
GPRel,
|
||||
|
||||
// Select CC Pseudo Instruction
|
||||
Select_CC,
|
||||
|
||||
// Wrap up multiple types of instructions
|
||||
Wrap,
|
||||
|
||||
// Integer Compare
|
||||
ICmp,
|
||||
|
||||
// Return from subroutine
|
||||
Ret,
|
||||
|
||||
// Return from interrupt
|
||||
IRet
|
||||
};
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// TargetLowering Implementation
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
class MBlazeTargetLowering : public TargetLowering {
|
||||
public:
|
||||
explicit MBlazeTargetLowering(MBlazeTargetMachine &TM);
|
||||
|
||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
/// getTargetNodeName - This method returns the name of a target specific
|
||||
// DAG node.
|
||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
||||
|
||||
/// getSetCCResultType - get the ISD::SETCC result ValueType
|
||||
EVT getSetCCResultType(LLVMContext &Context, EVT VT) const;
|
||||
|
||||
private:
|
||||
// Subtarget Info
|
||||
const MBlazeSubtarget *Subtarget;
|
||||
|
||||
|
||||
// Lower Operand helpers
|
||||
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
SDLoc dl, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const;
|
||||
|
||||
// Lower Operand specifics
|
||||
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
virtual SDValue
|
||||
LowerFormalArguments(SDValue Chain,
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
SDLoc dl, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const;
|
||||
|
||||
virtual SDValue
|
||||
LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
SmallVectorImpl<SDValue> &InVals) const;
|
||||
|
||||
virtual SDValue
|
||||
LowerReturn(SDValue Chain,
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
const SmallVectorImpl<SDValue> &OutVals,
|
||||
SDLoc dl, SelectionDAG &DAG) const;
|
||||
|
||||
virtual MachineBasicBlock*
|
||||
EmitCustomShift(MachineInstr *MI, MachineBasicBlock *MBB) const;
|
||||
|
||||
virtual MachineBasicBlock*
|
||||
EmitCustomSelect(MachineInstr *MI, MachineBasicBlock *MBB) const;
|
||||
|
||||
virtual MachineBasicBlock*
|
||||
EmitCustomAtomic(MachineInstr *MI, MachineBasicBlock *MBB) const;
|
||||
|
||||
virtual MachineBasicBlock *
|
||||
EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *MBB) const;
|
||||
|
||||
// Inline asm support
|
||||
ConstraintType getConstraintType(const std::string &Constraint) const;
|
||||
|
||||
/// Examine constraint string and operand type and determine a weight value.
|
||||
/// The operand object must already have been set up with the operand type.
|
||||
ConstraintWeight getSingleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, const char *constraint) const;
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass*>
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
MVT VT) const;
|
||||
|
||||
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
|
||||
|
||||
/// isFPImmLegal - Returns true if the target can instruction select the
|
||||
/// specified FP immediate natively. If false, the legalizer will
|
||||
/// materialize the FP immediate as a load from a constant pool.
|
||||
virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MBlazeISELLOWERING_H
|
@ -1,219 +0,0 @@
|
||||
//===-- MBlazeInstrFPU.td - MBlaze FPU Instruction defs ----*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze profiles and nodes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze Operand, Complex Patterns and Transformations Definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Memory Access Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
class LoadFM<bits<6> op, string instr_asm, PatFrag OpNode> :
|
||||
TA<op, 0x000, (outs GPR:$dst), (ins memrr:$addr),
|
||||
!strconcat(instr_asm, " $dst, $addr"),
|
||||
[(set (f32 GPR:$dst), (OpNode xaddr:$addr))], IIC_MEMl>;
|
||||
|
||||
class LoadFMI<bits<6> op, string instr_asm, PatFrag OpNode> :
|
||||
TB<op, (outs GPR:$dst), (ins memri:$addr),
|
||||
!strconcat(instr_asm, " $dst, $addr"),
|
||||
[(set (f32 GPR:$dst), (OpNode iaddr:$addr))], IIC_MEMl>;
|
||||
|
||||
class StoreFM<bits<6> op, string instr_asm, PatFrag OpNode> :
|
||||
TA<op, 0x000, (outs), (ins GPR:$dst, memrr:$addr),
|
||||
!strconcat(instr_asm, " $dst, $addr"),
|
||||
[(OpNode (f32 GPR:$dst), xaddr:$addr)], IIC_MEMs>;
|
||||
|
||||
class StoreFMI<bits<6> op, string instr_asm, PatFrag OpNode> :
|
||||
TB<op, (outs), (ins GPR:$dst, memrr:$addr),
|
||||
!strconcat(instr_asm, " $dst, $addr"),
|
||||
[(OpNode (f32 GPR:$dst), iaddr:$addr)], IIC_MEMs>;
|
||||
|
||||
class ArithF<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode,
|
||||
InstrItinClass itin> :
|
||||
TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c),
|
||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
||||
[(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], itin>;
|
||||
|
||||
class CmpFN<bits<6> op, bits<11> flags, string instr_asm,
|
||||
InstrItinClass itin> :
|
||||
TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c),
|
||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
||||
[], itin>;
|
||||
|
||||
class ArithFR<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode,
|
||||
InstrItinClass itin> :
|
||||
TAR<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c),
|
||||
!strconcat(instr_asm, " $dst, $c, $b"),
|
||||
[(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], itin>;
|
||||
|
||||
class LogicFI<bits<6> op, string instr_asm> :
|
||||
TB<op, (outs GPR:$dst), (ins GPR:$b, fimm:$c),
|
||||
!strconcat(instr_asm, " $dst, $b, $c"),
|
||||
[], IIC_ALU>;
|
||||
|
||||
let rb=0 in {
|
||||
class ArithF2<bits<6> op, bits<11> flags, string instr_asm,
|
||||
InstrItinClass itin> :
|
||||
TA<op, flags, (outs GPR:$dst), (ins GPR:$b),
|
||||
!strconcat(instr_asm, " $dst, $b"),
|
||||
[], itin>;
|
||||
|
||||
class ArithIF<bits<6> op, bits<11> flags, string instr_asm,
|
||||
InstrItinClass itin> :
|
||||
TA<op, flags, (outs GPR:$dst), (ins GPR:$b),
|
||||
!strconcat(instr_asm, " $dst, $b"),
|
||||
[], itin>;
|
||||
|
||||
class ArithFI<bits<6> op, bits<11> flags, string instr_asm,
|
||||
InstrItinClass itin> :
|
||||
TA<op, flags, (outs GPR:$dst), (ins GPR:$b),
|
||||
!strconcat(instr_asm, " $dst, $b"),
|
||||
[], itin>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pseudo instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FPU Arithmetic Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
let Predicates=[HasFPU] in {
|
||||
def FORI : LogicFI<0x28, "ori ">;
|
||||
def FADD : ArithF<0x16, 0x000, "fadd ", fadd, IIC_FPU>;
|
||||
def FRSUB : ArithFR<0x16, 0x080, "frsub ", fsub, IIC_FPU>;
|
||||
def FMUL : ArithF<0x16, 0x100, "fmul ", fmul, IIC_FPU>;
|
||||
def FDIV : ArithF<0x16, 0x180, "fdiv ", fdiv, IIC_FPUd>;
|
||||
}
|
||||
|
||||
let Predicates=[HasFPU], isCodeGenOnly=1 in {
|
||||
def LWF : LoadFM<0x32, "lw ", load>;
|
||||
def LWFI : LoadFMI<0x3A, "lwi ", load>;
|
||||
|
||||
def SWF : StoreFM<0x36, "sw ", store>;
|
||||
def SWFI : StoreFMI<0x3E, "swi ", store>;
|
||||
}
|
||||
|
||||
let Predicates=[HasFPU,HasSqrt] in {
|
||||
def FLT : ArithIF<0x16, 0x280, "flt ", IIC_FPUf>;
|
||||
def FINT : ArithFI<0x16, 0x300, "fint ", IIC_FPUi>;
|
||||
def FSQRT : ArithF2<0x16, 0x380, "fsqrt ", IIC_FPUs>;
|
||||
}
|
||||
|
||||
let isAsCheapAsAMove = 1 in {
|
||||
def FCMP_UN : CmpFN<0x16, 0x200, "fcmp.un", IIC_FPUc>;
|
||||
def FCMP_LT : CmpFN<0x16, 0x210, "fcmp.lt", IIC_FPUc>;
|
||||
def FCMP_EQ : CmpFN<0x16, 0x220, "fcmp.eq", IIC_FPUc>;
|
||||
def FCMP_LE : CmpFN<0x16, 0x230, "fcmp.le", IIC_FPUc>;
|
||||
def FCMP_GT : CmpFN<0x16, 0x240, "fcmp.gt", IIC_FPUc>;
|
||||
def FCMP_NE : CmpFN<0x16, 0x250, "fcmp.ne", IIC_FPUc>;
|
||||
def FCMP_GE : CmpFN<0x16, 0x260, "fcmp.ge", IIC_FPUc>;
|
||||
}
|
||||
|
||||
|
||||
let usesCustomInserter = 1 in {
|
||||
def Select_FCC : MBlazePseudo<(outs GPR:$dst),
|
||||
(ins GPR:$T, GPR:$F, GPR:$CMP, i32imm:$CC),
|
||||
"; SELECT_FCC PSEUDO!",
|
||||
[]>;
|
||||
}
|
||||
|
||||
// Floating point conversions
|
||||
let Predicates=[HasFPU] in {
|
||||
def : Pat<(sint_to_fp GPR:$V), (FLT GPR:$V)>;
|
||||
def : Pat<(fp_to_sint GPR:$V), (FINT GPR:$V)>;
|
||||
def : Pat<(fsqrt GPR:$V), (FSQRT GPR:$V)>;
|
||||
}
|
||||
|
||||
// SET_CC operations
|
||||
let Predicates=[HasFPU] in {
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETEQ),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_EQ GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETNE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_EQ GPR:$L, GPR:$R), 1)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOEQ),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_EQ GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETONE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(XOR (FCMP_UN GPR:$L, GPR:$R),
|
||||
(FCMP_EQ GPR:$L, GPR:$R)), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETONE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(OR (FCMP_UN GPR:$L, GPR:$R),
|
||||
(FCMP_EQ GPR:$L, GPR:$R)), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETGT),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_GT GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETLT),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_LT GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETGE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_GE GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETLE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_LE GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOGT),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_GT GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOLT),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_LT GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOGE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_GE GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOLE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_LE GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUEQ),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(OR (FCMP_UN GPR:$L, GPR:$R),
|
||||
(FCMP_EQ GPR:$L, GPR:$R)), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUNE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_NE GPR:$L, GPR:$R), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUGT),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(OR (FCMP_UN GPR:$L, GPR:$R),
|
||||
(FCMP_GT GPR:$L, GPR:$R)), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETULT),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(OR (FCMP_UN GPR:$L, GPR:$R),
|
||||
(FCMP_LT GPR:$L, GPR:$R)), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUGE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(OR (FCMP_UN GPR:$L, GPR:$R),
|
||||
(FCMP_GE GPR:$L, GPR:$R)), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETULE),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(OR (FCMP_UN GPR:$L, GPR:$R),
|
||||
(FCMP_LE GPR:$L, GPR:$R)), 2)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETO),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_UN GPR:$L, GPR:$R), 1)>;
|
||||
def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUO),
|
||||
(Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0),
|
||||
(FCMP_UN GPR:$L, GPR:$R), 2)>;
|
||||
}
|
||||
|
||||
// SELECT operations
|
||||
def : Pat<(select (i32 GPR:$C), (f32 GPR:$T), (f32 GPR:$F)),
|
||||
(Select_FCC GPR:$T, GPR:$F, GPR:$C, 2)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Patterns for Floating Point Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
def : Pat<(f32 fpimm:$imm), (FORI (i32 R0), fpimm:$imm)>;
|
@ -1,229 +0,0 @@
|
||||
//===-- MBlazeInstrFSL.td - MBlaze FSL Instruction defs ----*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FSL Instruction Formats
|
||||
//===----------------------------------------------------------------------===//
|
||||
class FSLGet<bits<6> op, bits<5> flags, string instr_asm, Intrinsic OpNode> :
|
||||
MBlazeInst<op, FRCX, (outs GPR:$dst), (ins fslimm:$b),
|
||||
!strconcat(instr_asm, " $dst, $b"),
|
||||
[(set GPR:$dst, (OpNode immZExt4:$b))],IIC_FSLg>
|
||||
{
|
||||
bits<5> rd;
|
||||
bits<4> fslno;
|
||||
|
||||
let Inst{6-10} = rd;
|
||||
let Inst{11-15} = 0x0;
|
||||
let Inst{16} = 0x0;
|
||||
let Inst{17-21} = flags; // NCTAE
|
||||
let Inst{22-27} = 0x0;
|
||||
let Inst{28-31} = fslno;
|
||||
}
|
||||
|
||||
class FSLGetD<bits<6> op, bits<5> flags, string instr_asm, Intrinsic OpNode> :
|
||||
MBlazeInst<op, FRCR, (outs GPR:$dst), (ins GPR:$b),
|
||||
!strconcat(instr_asm, " $dst, $b"),
|
||||
[(set GPR:$dst, (OpNode GPR:$b))], IIC_FSLg>
|
||||
{
|
||||
bits<5> rd;
|
||||
bits<5> rb;
|
||||
|
||||
let Inst{6-10} = rd;
|
||||
let Inst{11-15} = 0x0;
|
||||
let Inst{16-20} = rb;
|
||||
let Inst{21} = 0x0;
|
||||
let Inst{22-26} = flags; // NCTAE
|
||||
let Inst{27-31} = 0x0;
|
||||
}
|
||||
|
||||
class FSLPut<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> :
|
||||
MBlazeInst<op, FCRCX, (outs), (ins GPR:$v, fslimm:$b),
|
||||
!strconcat(instr_asm, " $v, $b"),
|
||||
[(OpNode GPR:$v, immZExt4:$b)], IIC_FSLp>
|
||||
{
|
||||
bits<5> ra;
|
||||
bits<4> fslno;
|
||||
|
||||
let Inst{6-10} = 0x0;
|
||||
let Inst{11-15} = ra;
|
||||
let Inst{16} = 0x1;
|
||||
let Inst{17-20} = flags; // NCTA
|
||||
let Inst{21-27} = 0x0;
|
||||
let Inst{28-31} = fslno;
|
||||
}
|
||||
|
||||
class FSLPutD<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> :
|
||||
MBlazeInst<op, FCRR, (outs), (ins GPR:$v, GPR:$b),
|
||||
!strconcat(instr_asm, " $v, $b"),
|
||||
[(OpNode GPR:$v, GPR:$b)], IIC_FSLp>
|
||||
{
|
||||
bits<5> ra;
|
||||
bits<5> rb;
|
||||
|
||||
let Inst{6-10} = 0x0;
|
||||
let Inst{11-15} = ra;
|
||||
let Inst{16-20} = rb;
|
||||
let Inst{21} = 0x1;
|
||||
let Inst{22-25} = flags; // NCTA
|
||||
let Inst{26-31} = 0x0;
|
||||
}
|
||||
|
||||
class FSLPutT<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> :
|
||||
MBlazeInst<op, FCX, (outs), (ins fslimm:$b),
|
||||
!strconcat(instr_asm, " $b"),
|
||||
[(OpNode immZExt4:$b)], IIC_FSLp>
|
||||
{
|
||||
bits<4> fslno;
|
||||
|
||||
let Inst{6-10} = 0x0;
|
||||
let Inst{11-15} = 0x0;
|
||||
let Inst{16} = 0x1;
|
||||
let Inst{17-20} = flags; // NCTA
|
||||
let Inst{21-27} = 0x0;
|
||||
let Inst{28-31} = fslno;
|
||||
}
|
||||
|
||||
class FSLPutTD<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> :
|
||||
MBlazeInst<op, FCR, (outs), (ins GPR:$b),
|
||||
!strconcat(instr_asm, " $b"),
|
||||
[(OpNode GPR:$b)], IIC_FSLp>
|
||||
{
|
||||
bits<5> rb;
|
||||
|
||||
let Inst{6-10} = 0x0;
|
||||
let Inst{11-15} = 0x0;
|
||||
let Inst{16-20} = rb;
|
||||
let Inst{21} = 0x1;
|
||||
let Inst{22-25} = flags; // NCTA
|
||||
let Inst{26-31} = 0x0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FSL Get Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
def GET : FSLGet<0x1B, 0x00, "get ", int_mblaze_fsl_get>;
|
||||
def AGET : FSLGet<0x1B, 0x02, "aget ", int_mblaze_fsl_aget>;
|
||||
def CGET : FSLGet<0x1B, 0x08, "cget ", int_mblaze_fsl_cget>;
|
||||
def CAGET : FSLGet<0x1B, 0x0A, "caget ", int_mblaze_fsl_caget>;
|
||||
def EGET : FSLGet<0x1B, 0x01, "eget ", int_mblaze_fsl_eget>;
|
||||
def EAGET : FSLGet<0x1B, 0x03, "eaget ", int_mblaze_fsl_eaget>;
|
||||
def ECGET : FSLGet<0x1B, 0x09, "ecget ", int_mblaze_fsl_ecget>;
|
||||
def ECAGET : FSLGet<0x1B, 0x0B, "ecaget ", int_mblaze_fsl_ecaget>;
|
||||
def TGET : FSLGet<0x1B, 0x04, "tget ", int_mblaze_fsl_tget>;
|
||||
def TAGET : FSLGet<0x1B, 0x06, "taget ", int_mblaze_fsl_taget>;
|
||||
def TCGET : FSLGet<0x1B, 0x0C, "tcget ", int_mblaze_fsl_tcget>;
|
||||
def TCAGET : FSLGet<0x1B, 0x0E, "tcaget ", int_mblaze_fsl_tcaget>;
|
||||
def TEGET : FSLGet<0x1B, 0x05, "teget ", int_mblaze_fsl_teget>;
|
||||
def TEAGET : FSLGet<0x1B, 0x07, "teaget ", int_mblaze_fsl_teaget>;
|
||||
def TECGET : FSLGet<0x1B, 0x0D, "tecget ", int_mblaze_fsl_tecget>;
|
||||
def TECAGET : FSLGet<0x1B, 0x0F, "tecaget ", int_mblaze_fsl_tecaget>;
|
||||
|
||||
let Defs = [CARRY] in {
|
||||
def NGET : FSLGet<0x1B, 0x10, "nget ", int_mblaze_fsl_nget>;
|
||||
def NAGET : FSLGet<0x1B, 0x12, "naget ", int_mblaze_fsl_naget>;
|
||||
def NCGET : FSLGet<0x1B, 0x18, "ncget ", int_mblaze_fsl_ncget>;
|
||||
def NCAGET : FSLGet<0x1B, 0x1A, "ncaget ", int_mblaze_fsl_ncaget>;
|
||||
def NEGET : FSLGet<0x1B, 0x11, "neget ", int_mblaze_fsl_neget>;
|
||||
def NEAGET : FSLGet<0x1B, 0x13, "neaget ", int_mblaze_fsl_neaget>;
|
||||
def NECGET : FSLGet<0x1B, 0x19, "necget ", int_mblaze_fsl_necget>;
|
||||
def NECAGET : FSLGet<0x1B, 0x1B, "necaget ", int_mblaze_fsl_necaget>;
|
||||
def TNGET : FSLGet<0x1B, 0x14, "tnget ", int_mblaze_fsl_tnget>;
|
||||
def TNAGET : FSLGet<0x1B, 0x16, "tnaget ", int_mblaze_fsl_tnaget>;
|
||||
def TNCGET : FSLGet<0x1B, 0x1C, "tncget ", int_mblaze_fsl_tncget>;
|
||||
def TNCAGET : FSLGet<0x1B, 0x1E, "tncaget ", int_mblaze_fsl_tncaget>;
|
||||
def TNEGET : FSLGet<0x1B, 0x15, "tneget ", int_mblaze_fsl_tneget>;
|
||||
def TNEAGET : FSLGet<0x1B, 0x17, "tneaget ", int_mblaze_fsl_tneaget>;
|
||||
def TNECGET : FSLGet<0x1B, 0x1D, "tnecget ", int_mblaze_fsl_tnecget>;
|
||||
def TNECAGET : FSLGet<0x1B, 0x1F, "tnecaget ", int_mblaze_fsl_tnecaget>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FSL Dynamic Get Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
def GETD : FSLGetD<0x13, 0x00, "getd ", int_mblaze_fsl_get>;
|
||||
def AGETD : FSLGetD<0x13, 0x02, "agetd ", int_mblaze_fsl_aget>;
|
||||
def CGETD : FSLGetD<0x13, 0x08, "cgetd ", int_mblaze_fsl_cget>;
|
||||
def CAGETD : FSLGetD<0x13, 0x0A, "cagetd ", int_mblaze_fsl_caget>;
|
||||
def EGETD : FSLGetD<0x13, 0x01, "egetd ", int_mblaze_fsl_eget>;
|
||||
def EAGETD : FSLGetD<0x13, 0x03, "eagetd ", int_mblaze_fsl_eaget>;
|
||||
def ECGETD : FSLGetD<0x13, 0x09, "ecgetd ", int_mblaze_fsl_ecget>;
|
||||
def ECAGETD : FSLGetD<0x13, 0x0B, "ecagetd ", int_mblaze_fsl_ecaget>;
|
||||
def TGETD : FSLGetD<0x13, 0x04, "tgetd ", int_mblaze_fsl_tget>;
|
||||
def TAGETD : FSLGetD<0x13, 0x06, "tagetd ", int_mblaze_fsl_taget>;
|
||||
def TCGETD : FSLGetD<0x13, 0x0C, "tcgetd ", int_mblaze_fsl_tcget>;
|
||||
def TCAGETD : FSLGetD<0x13, 0x0E, "tcagetd ", int_mblaze_fsl_tcaget>;
|
||||
def TEGETD : FSLGetD<0x13, 0x05, "tegetd ", int_mblaze_fsl_teget>;
|
||||
def TEAGETD : FSLGetD<0x13, 0x07, "teagetd ", int_mblaze_fsl_teaget>;
|
||||
def TECGETD : FSLGetD<0x13, 0x0D, "tecgetd ", int_mblaze_fsl_tecget>;
|
||||
def TECAGETD : FSLGetD<0x13, 0x0F, "tecagetd ", int_mblaze_fsl_tecaget>;
|
||||
|
||||
let Defs = [CARRY] in {
|
||||
def NGETD : FSLGetD<0x13, 0x10, "ngetd ", int_mblaze_fsl_nget>;
|
||||
def NAGETD : FSLGetD<0x13, 0x12, "nagetd ", int_mblaze_fsl_naget>;
|
||||
def NCGETD : FSLGetD<0x13, 0x18, "ncgetd ", int_mblaze_fsl_ncget>;
|
||||
def NCAGETD : FSLGetD<0x13, 0x1A, "ncagetd ", int_mblaze_fsl_ncaget>;
|
||||
def NEGETD : FSLGetD<0x13, 0x11, "negetd ", int_mblaze_fsl_neget>;
|
||||
def NEAGETD : FSLGetD<0x13, 0x13, "neagetd ", int_mblaze_fsl_neaget>;
|
||||
def NECGETD : FSLGetD<0x13, 0x19, "necgetd ", int_mblaze_fsl_necget>;
|
||||
def NECAGETD : FSLGetD<0x13, 0x1B, "necagetd ", int_mblaze_fsl_necaget>;
|
||||
def TNGETD : FSLGetD<0x13, 0x14, "tngetd ", int_mblaze_fsl_tnget>;
|
||||
def TNAGETD : FSLGetD<0x13, 0x16, "tnagetd ", int_mblaze_fsl_tnaget>;
|
||||
def TNCGETD : FSLGetD<0x13, 0x1C, "tncgetd ", int_mblaze_fsl_tncget>;
|
||||
def TNCAGETD : FSLGetD<0x13, 0x1E, "tncagetd ", int_mblaze_fsl_tncaget>;
|
||||
def TNEGETD : FSLGetD<0x13, 0x15, "tnegetd ", int_mblaze_fsl_tneget>;
|
||||
def TNEAGETD : FSLGetD<0x13, 0x17, "tneagetd ", int_mblaze_fsl_tneaget>;
|
||||
def TNECGETD : FSLGetD<0x13, 0x1D, "tnecgetd ", int_mblaze_fsl_tnecget>;
|
||||
def TNECAGETD : FSLGetD<0x13, 0x1F, "tnecagetd", int_mblaze_fsl_tnecaget>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FSL Put Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
def PUT : FSLPut<0x1B, 0x0, "put ", int_mblaze_fsl_put>;
|
||||
def APUT : FSLPut<0x1B, 0x1, "aput ", int_mblaze_fsl_aput>;
|
||||
def CPUT : FSLPut<0x1B, 0x4, "cput ", int_mblaze_fsl_cput>;
|
||||
def CAPUT : FSLPut<0x1B, 0x5, "caput ", int_mblaze_fsl_caput>;
|
||||
def TPUT : FSLPutT<0x1B, 0x2, "tput ", int_mblaze_fsl_tput>;
|
||||
def TAPUT : FSLPutT<0x1B, 0x3, "taput ", int_mblaze_fsl_taput>;
|
||||
def TCPUT : FSLPutT<0x1B, 0x6, "tcput ", int_mblaze_fsl_tcput>;
|
||||
def TCAPUT : FSLPutT<0x1B, 0x7, "tcaput ", int_mblaze_fsl_tcaput>;
|
||||
|
||||
let Defs = [CARRY] in {
|
||||
def NPUT : FSLPut<0x1B, 0x8, "nput ", int_mblaze_fsl_nput>;
|
||||
def NAPUT : FSLPut<0x1B, 0x9, "naput ", int_mblaze_fsl_naput>;
|
||||
def NCPUT : FSLPut<0x1B, 0xC, "ncput ", int_mblaze_fsl_ncput>;
|
||||
def NCAPUT : FSLPut<0x1B, 0xD, "ncaput ", int_mblaze_fsl_ncaput>;
|
||||
def TNPUT : FSLPutT<0x1B, 0xA, "tnput ", int_mblaze_fsl_tnput>;
|
||||
def TNAPUT : FSLPutT<0x1B, 0xB, "tnaput ", int_mblaze_fsl_tnaput>;
|
||||
def TNCPUT : FSLPutT<0x1B, 0xE, "tncput ", int_mblaze_fsl_tncput>;
|
||||
def TNCAPUT : FSLPutT<0x1B, 0xF, "tncaput ", int_mblaze_fsl_tncaput>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FSL Dynamic Put Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
def PUTD : FSLPutD<0x13, 0x0, "putd ", int_mblaze_fsl_put>;
|
||||
def APUTD : FSLPutD<0x13, 0x1, "aputd ", int_mblaze_fsl_aput>;
|
||||
def CPUTD : FSLPutD<0x13, 0x4, "cputd ", int_mblaze_fsl_cput>;
|
||||
def CAPUTD : FSLPutD<0x13, 0x5, "caputd ", int_mblaze_fsl_caput>;
|
||||
def TPUTD : FSLPutTD<0x13, 0x2, "tputd ", int_mblaze_fsl_tput>;
|
||||
def TAPUTD : FSLPutTD<0x13, 0x3, "taputd ", int_mblaze_fsl_taput>;
|
||||
def TCPUTD : FSLPutTD<0x13, 0x6, "tcputd ", int_mblaze_fsl_tcput>;
|
||||
def TCAPUTD : FSLPutTD<0x13, 0x7, "tcaputd ", int_mblaze_fsl_tcaput>;
|
||||
|
||||
let Defs = [CARRY] in {
|
||||
def NPUTD : FSLPutD<0x13, 0x8, "nputd ", int_mblaze_fsl_nput>;
|
||||
def NAPUTD : FSLPutD<0x13, 0x9, "naputd ", int_mblaze_fsl_naput>;
|
||||
def NCPUTD : FSLPutD<0x13, 0xC, "ncputd ", int_mblaze_fsl_ncput>;
|
||||
def NCAPUTD : FSLPutD<0x13, 0xD, "ncaputd ", int_mblaze_fsl_ncaput>;
|
||||
def TNPUTD : FSLPutTD<0x13, 0xA, "tnputd ", int_mblaze_fsl_tnput>;
|
||||
def TNAPUTD : FSLPutTD<0x13, 0xB, "tnaputd ", int_mblaze_fsl_tnaput>;
|
||||
def TNCPUTD : FSLPutTD<0x13, 0xE, "tncputd ", int_mblaze_fsl_tncput>;
|
||||
def TNCAPUTD : FSLPutTD<0x13, 0xF, "tncaputd ", int_mblaze_fsl_tncaput>;
|
||||
}
|
@ -1,228 +0,0 @@
|
||||
//===-- MBlazeInstrFormats.td - MB Instruction defs --------*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Format specifies the encoding used by the instruction. This is part of the
|
||||
// ad-hoc solution used to emit machine instruction encodings by our machine
|
||||
// code emitter.
|
||||
class Format<bits<6> val> {
|
||||
bits<6> Value = val;
|
||||
}
|
||||
|
||||
def FPseudo : Format<0>;
|
||||
def FRRR : Format<1>; // ADD, OR, etc.
|
||||
def FRRI : Format<2>; // ADDI, ORI, etc.
|
||||
def FCRR : Format<3>; // PUTD, WDC, WIC, BEQ, BNE, BGE, etc.
|
||||
def FCRI : Format<4>; // RTID, RTED, RTSD, BEQI, BNEI, BGEI, etc.
|
||||
def FRCR : Format<5>; // BRLD, BRALD, GETD
|
||||
def FRCI : Format<6>; // BRLID, BRALID, MSRCLR, MSRSET
|
||||
def FCCR : Format<7>; // BR, BRA, BRD, etc.
|
||||
def FCCI : Format<8>; // IMM, BRI, BRAI, BRID, etc.
|
||||
def FRRCI : Format<9>; // BSRLI, BSRAI, BSLLI
|
||||
def FRRC : Format<10>; // SEXT8, SEXT16, SRA, SRC, SRL, FLT, FINT, FSQRT
|
||||
def FRCX : Format<11>; // GET
|
||||
def FRCS : Format<12>; // MFS
|
||||
def FCRCS : Format<13>; // MTS
|
||||
def FCRCX : Format<14>; // PUT
|
||||
def FCX : Format<15>; // TPUT
|
||||
def FCR : Format<16>; // TPUTD
|
||||
def FRIR : Format<17>; // RSUBI
|
||||
def FRRRR : Format<18>; // RSUB, FRSUB
|
||||
def FRI : Format<19>; // RSUB, FRSUB
|
||||
def FC : Format<20>; // NOP
|
||||
def FRR : Format<21>; // CLZ
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Describe MBlaze instructions format
|
||||
//
|
||||
// CPU INSTRUCTION FORMATS
|
||||
//
|
||||
// opcode - operation code.
|
||||
// rd - dst reg.
|
||||
// ra - first src. reg.
|
||||
// rb - second src. reg.
|
||||
// imm16 - 16-bit immediate value.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Generic MBlaze Format
|
||||
class MBlazeInst<bits<6> op, Format form, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> : Instruction {
|
||||
let Namespace = "MBlaze";
|
||||
field bits<32> Inst;
|
||||
|
||||
bits<6> opcode = op;
|
||||
Format Form = form;
|
||||
bits<6> FormBits = Form.Value;
|
||||
|
||||
// Top 6 bits are the 'opcode' field
|
||||
let Inst{0-5} = opcode;
|
||||
|
||||
// If the instruction is marked as a pseudo, set isCodeGenOnly so that the
|
||||
// assembler and disassmbler ignore it.
|
||||
let isCodeGenOnly = !eq(!cast<string>(form), "FPseudo");
|
||||
|
||||
dag OutOperandList = outs;
|
||||
dag InOperandList = ins;
|
||||
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
let Itinerary = itin;
|
||||
|
||||
// TSFlags layout should be kept in sync with MBlazeInstrInfo.h.
|
||||
let TSFlags{5-0} = FormBits;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pseudo instruction class
|
||||
//===----------------------------------------------------------------------===//
|
||||
class MBlazePseudo<dag outs, dag ins, string asmstr, list<dag> pattern>:
|
||||
MBlazeInst<0x0, FPseudo, outs, ins, asmstr, pattern, IIC_Pseudo>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type A instruction class in MBlaze : <|opcode|rd|ra|rb|flags|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class TA<bits<6> op, bits<11> flags, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
MBlazeInst<op,FRRR,outs, ins, asmstr, pattern, itin>
|
||||
{
|
||||
bits<5> rd;
|
||||
bits<5> ra;
|
||||
bits<5> rb;
|
||||
|
||||
let Inst{6-10} = rd;
|
||||
let Inst{11-15} = ra;
|
||||
let Inst{16-20} = rb;
|
||||
let Inst{21-31} = flags;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type B instruction class in MBlaze : <|opcode|rd|ra|immediate|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class TB<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin> :
|
||||
MBlazeInst<op, FRRI, outs, ins, asmstr, pattern, itin>
|
||||
{
|
||||
bits<5> rd;
|
||||
bits<5> ra;
|
||||
bits<16> imm16;
|
||||
|
||||
let Inst{6-10} = rd;
|
||||
let Inst{11-15} = ra;
|
||||
let Inst{16-31} = imm16;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type A instruction class in MBlaze but with the operands reversed
|
||||
// in the LLVM DAG : <|opcode|rd|ra|rb|flags|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class TAR<bits<6> op, bits<11> flags, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
TA<op, flags, outs, ins, asmstr, pattern, itin>
|
||||
{
|
||||
bits<5> rrd;
|
||||
bits<5> rrb;
|
||||
bits<5> rra;
|
||||
|
||||
let Form = FRRRR;
|
||||
|
||||
let rd = rrd;
|
||||
let ra = rra;
|
||||
let rb = rrb;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type B instruction class in MBlaze but with the operands reversed in
|
||||
// the LLVM DAG : <|opcode|rd|ra|immediate|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
class TBR<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin> :
|
||||
TB<op, outs, ins, asmstr, pattern, itin> {
|
||||
bits<5> rrd;
|
||||
bits<16> rimm16;
|
||||
bits<5> rra;
|
||||
|
||||
let Form = FRIR;
|
||||
|
||||
let rd = rrd;
|
||||
let ra = rra;
|
||||
let imm16 = rimm16;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Shift immediate instruction class in MBlaze : <|opcode|rd|ra|immediate|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
class SHT<bits<6> op, bits<2> flags, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
MBlazeInst<op, FRRI, outs, ins, asmstr, pattern, itin> {
|
||||
bits<5> rd;
|
||||
bits<5> ra;
|
||||
bits<5> imm5;
|
||||
|
||||
let Inst{6-10} = rd;
|
||||
let Inst{11-15} = ra;
|
||||
let Inst{16-20} = 0x0;
|
||||
let Inst{21-22} = flags;
|
||||
let Inst{23-26} = 0x0;
|
||||
let Inst{27-31} = imm5;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Special instruction class in MBlaze : <|opcode|rd|imm14|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
class SPC<bits<6> op, bits<2> flags, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
MBlazeInst<op, FRI, outs, ins, asmstr, pattern, itin> {
|
||||
bits<5> rd;
|
||||
bits<14> imm14;
|
||||
|
||||
let Inst{6-10} = rd;
|
||||
let Inst{11-15} = 0x0;
|
||||
let Inst{16-17} = flags;
|
||||
let Inst{18-31} = imm14;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MSR instruction class in MBlaze : <|opcode|rd|imm15|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
class MSR<bits<6> op, bits<6> flags, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
MBlazeInst<op, FRI, outs, ins, asmstr, pattern, itin> {
|
||||
bits<5> rd;
|
||||
bits<15> imm15;
|
||||
|
||||
let Inst{6-10} = rd;
|
||||
let Inst{11-16} = flags;
|
||||
let Inst{17-31} = imm15;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TCLZ instruction class in MBlaze : <|opcode|rd|imm15|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
class TCLZ<bits<6> op, bits<16> flags, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
MBlazeInst<op, FRR, outs, ins, asmstr, pattern, itin> {
|
||||
bits<5> rd;
|
||||
bits<5> ra;
|
||||
|
||||
let Inst{6-10} = rd;
|
||||
let Inst{11-15} = ra;
|
||||
let Inst{16-31} = flags;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBAR instruction class in MBlaze : <|opcode|rd|imm15|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
class MBAR<bits<6> op, bits<26> flags, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
MBlazeInst<op, FC, outs, ins, asmstr, pattern, itin> {
|
||||
let Inst{6-31} = flags;
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
//===-- MBlazeInstrInfo.cpp - MBlaze Instruction Information --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the MBlaze implementation of the TargetInstrInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeInstrInfo.h"
|
||||
#include "MBlazeMachineFunction.h"
|
||||
#include "MBlazeTargetMachine.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
#define GET_INSTRINFO_CTOR
|
||||
#include "MBlazeGenInstrInfo.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MBlazeInstrInfo::MBlazeInstrInfo(MBlazeTargetMachine &tm)
|
||||
: MBlazeGenInstrInfo(MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP),
|
||||
TM(tm), RI(*TM.getSubtargetImpl()) {}
|
||||
|
||||
static bool isZeroImm(const MachineOperand &op) {
|
||||
return op.isImm() && op.getImm() == 0;
|
||||
}
|
||||
|
||||
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
||||
/// load from a stack slot, return the virtual or physical register number of
|
||||
/// the destination along with the FrameIndex of the loaded stack slot. If
|
||||
/// not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than loading from the stack slot.
|
||||
unsigned MBlazeInstrInfo::
|
||||
isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const {
|
||||
if (MI->getOpcode() == MBlaze::LWI) {
|
||||
if ((MI->getOperand(1).isFI()) && // is a stack slot
|
||||
(MI->getOperand(2).isImm()) && // the imm is zero
|
||||
(isZeroImm(MI->getOperand(2)))) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
||||
/// store to a stack slot, return the virtual or physical register number of
|
||||
/// the source reg along with the FrameIndex of the loaded stack slot. If
|
||||
/// not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than storing to the stack slot.
|
||||
unsigned MBlazeInstrInfo::
|
||||
isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const {
|
||||
if (MI->getOpcode() == MBlaze::SWI) {
|
||||
if ((MI->getOperand(1).isFI()) && // is a stack slot
|
||||
(MI->getOperand(2).isImm()) && // the imm is zero
|
||||
(isZeroImm(MI->getOperand(2)))) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// insertNoop - If data hazard condition is found insert the target nop
|
||||
/// instruction.
|
||||
void MBlazeInstrInfo::
|
||||
insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const {
|
||||
DebugLoc DL;
|
||||
BuildMI(MBB, MI, DL, get(MBlaze::NOP));
|
||||
}
|
||||
|
||||
void MBlazeInstrInfo::
|
||||
copyPhysReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
bool KillSrc) const {
|
||||
llvm::BuildMI(MBB, I, DL, get(MBlaze::ADDK), DestReg)
|
||||
.addReg(SrcReg, getKillRegState(KillSrc)).addReg(MBlaze::R0);
|
||||
}
|
||||
|
||||
void MBlazeInstrInfo::
|
||||
storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned SrcReg, bool isKill, int FI,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
DebugLoc DL;
|
||||
BuildMI(MBB, I, DL, get(MBlaze::SWI)).addReg(SrcReg,getKillRegState(isKill))
|
||||
.addFrameIndex(FI).addImm(0); //.addFrameIndex(FI);
|
||||
}
|
||||
|
||||
void MBlazeInstrInfo::
|
||||
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, int FI,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
DebugLoc DL;
|
||||
BuildMI(MBB, I, DL, get(MBlaze::LWI), DestReg)
|
||||
.addFrameIndex(FI).addImm(0); //.addFrameIndex(FI);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Branch Analysis
|
||||
//===----------------------------------------------------------------------===//
|
||||
bool MBlazeInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const {
|
||||
// If the block has no terminators, it just falls into the block after it.
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
if (I == MBB.begin())
|
||||
return false;
|
||||
--I;
|
||||
while (I->isDebugValue()) {
|
||||
if (I == MBB.begin())
|
||||
return false;
|
||||
--I;
|
||||
}
|
||||
if (!isUnpredicatedTerminator(I))
|
||||
return false;
|
||||
|
||||
// Get the last instruction in the block.
|
||||
MachineInstr *LastInst = I;
|
||||
|
||||
// If there is only one terminator instruction, process it.
|
||||
unsigned LastOpc = LastInst->getOpcode();
|
||||
if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
|
||||
if (MBlaze::isUncondBranchOpcode(LastOpc)) {
|
||||
TBB = LastInst->getOperand(0).getMBB();
|
||||
return false;
|
||||
}
|
||||
if (MBlaze::isCondBranchOpcode(LastOpc)) {
|
||||
// Block ends with fall-through condbranch.
|
||||
TBB = LastInst->getOperand(1).getMBB();
|
||||
Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
|
||||
Cond.push_back(LastInst->getOperand(0));
|
||||
return false;
|
||||
}
|
||||
// Otherwise, don't know what this is.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the instruction before it if it's a terminator.
|
||||
MachineInstr *SecondLastInst = I;
|
||||
|
||||
// If there are three terminators, we don't know what sort of block this is.
|
||||
if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I))
|
||||
return true;
|
||||
|
||||
// If the block ends with something like BEQID then BRID, handle it.
|
||||
if (MBlaze::isCondBranchOpcode(SecondLastInst->getOpcode()) &&
|
||||
MBlaze::isUncondBranchOpcode(LastInst->getOpcode())) {
|
||||
TBB = SecondLastInst->getOperand(1).getMBB();
|
||||
Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode()));
|
||||
Cond.push_back(SecondLastInst->getOperand(0));
|
||||
FBB = LastInst->getOperand(0).getMBB();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the block ends with two unconditional branches, handle it.
|
||||
// The second one is not executed, so remove it.
|
||||
if (MBlaze::isUncondBranchOpcode(SecondLastInst->getOpcode()) &&
|
||||
MBlaze::isUncondBranchOpcode(LastInst->getOpcode())) {
|
||||
TBB = SecondLastInst->getOperand(0).getMBB();
|
||||
I = LastInst;
|
||||
if (AllowModify)
|
||||
I->eraseFromParent();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, can't handle this.
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned MBlazeInstrInfo::
|
||||
InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond,
|
||||
DebugLoc DL) const {
|
||||
// Shouldn't be a fall through.
|
||||
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
||||
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
||||
"MBlaze branch conditions have two components!");
|
||||
|
||||
unsigned Opc = MBlaze::BRID;
|
||||
if (!Cond.empty())
|
||||
Opc = (unsigned)Cond[0].getImm();
|
||||
|
||||
if (FBB == 0) {
|
||||
if (Cond.empty()) // Unconditional branch
|
||||
BuildMI(&MBB, DL, get(Opc)).addMBB(TBB);
|
||||
else // Conditional branch
|
||||
BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()).addMBB(TBB);
|
||||
return 1;
|
||||
}
|
||||
|
||||
BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()).addMBB(TBB);
|
||||
BuildMI(&MBB, DL, get(MBlaze::BRID)).addMBB(FBB);
|
||||
return 2;
|
||||
}
|
||||
|
||||
unsigned MBlazeInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator I = MBB.end();
|
||||
if (I == MBB.begin()) return 0;
|
||||
--I;
|
||||
while (I->isDebugValue()) {
|
||||
if (I == MBB.begin())
|
||||
return 0;
|
||||
--I;
|
||||
}
|
||||
|
||||
if (!MBlaze::isUncondBranchOpcode(I->getOpcode()) &&
|
||||
!MBlaze::isCondBranchOpcode(I->getOpcode()))
|
||||
return 0;
|
||||
|
||||
// Remove the branch.
|
||||
I->eraseFromParent();
|
||||
|
||||
I = MBB.end();
|
||||
|
||||
if (I == MBB.begin()) return 1;
|
||||
--I;
|
||||
if (!MBlaze::isCondBranchOpcode(I->getOpcode()))
|
||||
return 1;
|
||||
|
||||
// Remove the branch.
|
||||
I->eraseFromParent();
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool MBlazeInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand>
|
||||
&Cond) const {
|
||||
assert(Cond.size() == 2 && "Invalid MBlaze branch opcode!");
|
||||
switch (Cond[0].getImm()) {
|
||||
default: return true;
|
||||
case MBlaze::BEQ: Cond[0].setImm(MBlaze::BNE); return false;
|
||||
case MBlaze::BNE: Cond[0].setImm(MBlaze::BEQ); return false;
|
||||
case MBlaze::BGT: Cond[0].setImm(MBlaze::BLE); return false;
|
||||
case MBlaze::BGE: Cond[0].setImm(MBlaze::BLT); return false;
|
||||
case MBlaze::BLT: Cond[0].setImm(MBlaze::BGE); return false;
|
||||
case MBlaze::BLE: Cond[0].setImm(MBlaze::BGT); return false;
|
||||
case MBlaze::BEQI: Cond[0].setImm(MBlaze::BNEI); return false;
|
||||
case MBlaze::BNEI: Cond[0].setImm(MBlaze::BEQI); return false;
|
||||
case MBlaze::BGTI: Cond[0].setImm(MBlaze::BLEI); return false;
|
||||
case MBlaze::BGEI: Cond[0].setImm(MBlaze::BLTI); return false;
|
||||
case MBlaze::BLTI: Cond[0].setImm(MBlaze::BGEI); return false;
|
||||
case MBlaze::BLEI: Cond[0].setImm(MBlaze::BGTI); return false;
|
||||
case MBlaze::BEQD: Cond[0].setImm(MBlaze::BNED); return false;
|
||||
case MBlaze::BNED: Cond[0].setImm(MBlaze::BEQD); return false;
|
||||
case MBlaze::BGTD: Cond[0].setImm(MBlaze::BLED); return false;
|
||||
case MBlaze::BGED: Cond[0].setImm(MBlaze::BLTD); return false;
|
||||
case MBlaze::BLTD: Cond[0].setImm(MBlaze::BGED); return false;
|
||||
case MBlaze::BLED: Cond[0].setImm(MBlaze::BGTD); return false;
|
||||
case MBlaze::BEQID: Cond[0].setImm(MBlaze::BNEID); return false;
|
||||
case MBlaze::BNEID: Cond[0].setImm(MBlaze::BEQID); return false;
|
||||
case MBlaze::BGTID: Cond[0].setImm(MBlaze::BLEID); return false;
|
||||
case MBlaze::BGEID: Cond[0].setImm(MBlaze::BLTID); return false;
|
||||
case MBlaze::BLTID: Cond[0].setImm(MBlaze::BGEID); return false;
|
||||
case MBlaze::BLEID: Cond[0].setImm(MBlaze::BGTID); return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// getGlobalBaseReg - Return a virtual register initialized with the
|
||||
/// the global base register value. Output instructions required to
|
||||
/// initialize the register in the function entry block, if necessary.
|
||||
///
|
||||
unsigned MBlazeInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
|
||||
MBlazeFunctionInfo *MBlazeFI = MF->getInfo<MBlazeFunctionInfo>();
|
||||
unsigned GlobalBaseReg = MBlazeFI->getGlobalBaseReg();
|
||||
if (GlobalBaseReg != 0)
|
||||
return GlobalBaseReg;
|
||||
|
||||
// Insert the set of GlobalBaseReg into the first MBB of the function
|
||||
MachineBasicBlock &FirstMBB = MF->front();
|
||||
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
|
||||
MachineRegisterInfo &RegInfo = MF->getRegInfo();
|
||||
const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
|
||||
|
||||
GlobalBaseReg = RegInfo.createVirtualRegister(&MBlaze::GPRRegClass);
|
||||
BuildMI(FirstMBB, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY),
|
||||
GlobalBaseReg).addReg(MBlaze::R20);
|
||||
RegInfo.addLiveIn(MBlaze::R20);
|
||||
|
||||
MBlazeFI->setGlobalBaseReg(GlobalBaseReg);
|
||||
return GlobalBaseReg;
|
||||
}
|
@ -1,240 +0,0 @@
|
||||
//===-- MBlazeInstrInfo.h - MBlaze 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 MBlaze implementation of the TargetInstrInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZEINSTRUCTIONINFO_H
|
||||
#define MBLAZEINSTRUCTIONINFO_H
|
||||
|
||||
#include "MBlaze.h"
|
||||
#include "MBlazeRegisterInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
|
||||
#define GET_INSTRINFO_HEADER
|
||||
#include "MBlazeGenInstrInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace MBlaze {
|
||||
|
||||
// MBlaze Branch Codes
|
||||
enum FPBranchCode {
|
||||
BRANCH_F,
|
||||
BRANCH_T,
|
||||
BRANCH_FL,
|
||||
BRANCH_TL,
|
||||
BRANCH_INVALID
|
||||
};
|
||||
|
||||
// MBlaze Condition Codes
|
||||
enum CondCode {
|
||||
// To be used with float branch True
|
||||
FCOND_F,
|
||||
FCOND_UN,
|
||||
FCOND_EQ,
|
||||
FCOND_UEQ,
|
||||
FCOND_OLT,
|
||||
FCOND_ULT,
|
||||
FCOND_OLE,
|
||||
FCOND_ULE,
|
||||
FCOND_SF,
|
||||
FCOND_NGLE,
|
||||
FCOND_SEQ,
|
||||
FCOND_NGL,
|
||||
FCOND_LT,
|
||||
FCOND_NGE,
|
||||
FCOND_LE,
|
||||
FCOND_NGT,
|
||||
|
||||
// To be used with float branch False
|
||||
// This conditions have the same mnemonic as the
|
||||
// above ones, but are used with a branch False;
|
||||
FCOND_T,
|
||||
FCOND_OR,
|
||||
FCOND_NEQ,
|
||||
FCOND_OGL,
|
||||
FCOND_UGE,
|
||||
FCOND_OGE,
|
||||
FCOND_UGT,
|
||||
FCOND_OGT,
|
||||
FCOND_ST,
|
||||
FCOND_GLE,
|
||||
FCOND_SNE,
|
||||
FCOND_GL,
|
||||
FCOND_NLT,
|
||||
FCOND_GE,
|
||||
FCOND_NLE,
|
||||
FCOND_GT,
|
||||
|
||||
// Only integer conditions
|
||||
COND_EQ,
|
||||
COND_GT,
|
||||
COND_GE,
|
||||
COND_LT,
|
||||
COND_LE,
|
||||
COND_NE,
|
||||
COND_INVALID
|
||||
};
|
||||
|
||||
// Turn condition code into conditional branch opcode.
|
||||
inline static unsigned GetCondBranchFromCond(CondCode CC) {
|
||||
switch (CC) {
|
||||
default: llvm_unreachable("Unknown condition code");
|
||||
case COND_EQ: return MBlaze::BEQID;
|
||||
case COND_NE: return MBlaze::BNEID;
|
||||
case COND_GT: return MBlaze::BGTID;
|
||||
case COND_GE: return MBlaze::BGEID;
|
||||
case COND_LT: return MBlaze::BLTID;
|
||||
case COND_LE: return MBlaze::BLEID;
|
||||
}
|
||||
}
|
||||
|
||||
/// GetOppositeBranchCondition - Return the inverse of the specified cond,
|
||||
/// e.g. turning COND_E to COND_NE.
|
||||
// CondCode GetOppositeBranchCondition(MBlaze::CondCode CC);
|
||||
|
||||
/// MBlazeCCToString - Map each FP condition code to its string
|
||||
inline static const char *MBlazeFCCToString(MBlaze::CondCode CC) {
|
||||
switch (CC) {
|
||||
default: llvm_unreachable("Unknown condition code");
|
||||
case FCOND_F:
|
||||
case FCOND_T: return "f";
|
||||
case FCOND_UN:
|
||||
case FCOND_OR: return "un";
|
||||
case FCOND_EQ:
|
||||
case FCOND_NEQ: return "eq";
|
||||
case FCOND_UEQ:
|
||||
case FCOND_OGL: return "ueq";
|
||||
case FCOND_OLT:
|
||||
case FCOND_UGE: return "olt";
|
||||
case FCOND_ULT:
|
||||
case FCOND_OGE: return "ult";
|
||||
case FCOND_OLE:
|
||||
case FCOND_UGT: return "ole";
|
||||
case FCOND_ULE:
|
||||
case FCOND_OGT: return "ule";
|
||||
case FCOND_SF:
|
||||
case FCOND_ST: return "sf";
|
||||
case FCOND_NGLE:
|
||||
case FCOND_GLE: return "ngle";
|
||||
case FCOND_SEQ:
|
||||
case FCOND_SNE: return "seq";
|
||||
case FCOND_NGL:
|
||||
case FCOND_GL: return "ngl";
|
||||
case FCOND_LT:
|
||||
case FCOND_NLT: return "lt";
|
||||
case FCOND_NGE:
|
||||
case FCOND_GE: return "ge";
|
||||
case FCOND_LE:
|
||||
case FCOND_NLE: return "nle";
|
||||
case FCOND_NGT:
|
||||
case FCOND_GT: return "gt";
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool isUncondBranchOpcode(int Opc) {
|
||||
switch (Opc) {
|
||||
default: return false;
|
||||
case MBlaze::BRI:
|
||||
case MBlaze::BRAI:
|
||||
case MBlaze::BRID:
|
||||
case MBlaze::BRAID:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline static bool isCondBranchOpcode(int Opc) {
|
||||
switch (Opc) {
|
||||
default: return false;
|
||||
case MBlaze::BEQI: case MBlaze::BEQID:
|
||||
case MBlaze::BNEI: case MBlaze::BNEID:
|
||||
case MBlaze::BGTI: case MBlaze::BGTID:
|
||||
case MBlaze::BGEI: case MBlaze::BGEID:
|
||||
case MBlaze::BLTI: case MBlaze::BLTID:
|
||||
case MBlaze::BLEI: case MBlaze::BLEID:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MBlazeInstrInfo : public MBlazeGenInstrInfo {
|
||||
MBlazeTargetMachine &TM;
|
||||
const MBlazeRegisterInfo RI;
|
||||
public:
|
||||
explicit MBlazeInstrInfo(MBlazeTargetMachine &TM);
|
||||
|
||||
/// 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 MBlazeRegisterInfo &getRegisterInfo() const { return RI; }
|
||||
|
||||
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
||||
/// load from a stack slot, return the virtual or physical register number of
|
||||
/// the destination along with the FrameIndex of the loaded stack slot. If
|
||||
/// not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than loading from the stack slot.
|
||||
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
||||
/// store to a stack slot, return the virtual or physical register number of
|
||||
/// the source reg along with the FrameIndex of the loaded stack slot. If
|
||||
/// not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than storing to the stack slot.
|
||||
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
/// Branch Analysis
|
||||
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const;
|
||||
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond,
|
||||
DebugLoc DL) const;
|
||||
virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const;
|
||||
|
||||
virtual bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond)
|
||||
const;
|
||||
|
||||
virtual void copyPhysReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
bool KillSrc) const;
|
||||
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned SrcReg, bool isKill, int FrameIndex,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
|
||||
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
|
||||
/// Insert nop instruction when hazard condition is found
|
||||
virtual void insertNoop(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI) const;
|
||||
|
||||
/// getGlobalBaseReg - Return a virtual register initialized with the
|
||||
/// the global base register value. Output instructions required to
|
||||
/// initialize the register in the function entry block, if necessary.
|
||||
///
|
||||
unsigned getGlobalBaseReg(MachineFunction *MF) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,111 +0,0 @@
|
||||
//===-- MBlazeIntrinsicInfo.cpp - Intrinsic 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 MBlaze implementation of TargetIntrinsicInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeIntrinsicInfo.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstring>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace mblazeIntrinsic {
|
||||
|
||||
enum ID {
|
||||
last_non_mblaze_intrinsic = Intrinsic::num_intrinsics-1,
|
||||
#define GET_INTRINSIC_ENUM_VALUES
|
||||
#include "MBlazeGenIntrinsics.inc"
|
||||
#undef GET_INTRINSIC_ENUM_VALUES
|
||||
, num_mblaze_intrinsics
|
||||
};
|
||||
|
||||
#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
|
||||
#include "MBlazeGenIntrinsics.inc"
|
||||
#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
|
||||
}
|
||||
|
||||
std::string MBlazeIntrinsicInfo::getName(unsigned IntrID, Type **Tys,
|
||||
unsigned numTys) const {
|
||||
static const char *const names[] = {
|
||||
#define GET_INTRINSIC_NAME_TABLE
|
||||
#include "MBlazeGenIntrinsics.inc"
|
||||
#undef GET_INTRINSIC_NAME_TABLE
|
||||
};
|
||||
|
||||
assert(!isOverloaded(IntrID) && "MBlaze intrinsics are not overloaded");
|
||||
if (IntrID < Intrinsic::num_intrinsics)
|
||||
return 0;
|
||||
assert(IntrID < mblazeIntrinsic::num_mblaze_intrinsics &&
|
||||
"Invalid intrinsic ID");
|
||||
|
||||
std::string Result(names[IntrID - Intrinsic::num_intrinsics]);
|
||||
return Result;
|
||||
}
|
||||
|
||||
unsigned MBlazeIntrinsicInfo::
|
||||
lookupName(const char *Name, unsigned Len) const {
|
||||
if (!StringRef(Name, Len).startswith("llvm."))
|
||||
return 0; // All intrinsics start with 'llvm.'
|
||||
|
||||
#define GET_FUNCTION_RECOGNIZER
|
||||
#include "MBlazeGenIntrinsics.inc"
|
||||
#undef GET_FUNCTION_RECOGNIZER
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned MBlazeIntrinsicInfo::
|
||||
lookupGCCName(const char *Name) const {
|
||||
return mblazeIntrinsic::getIntrinsicForGCCBuiltin("mblaze",Name);
|
||||
}
|
||||
|
||||
bool MBlazeIntrinsicInfo::isOverloaded(unsigned IntrID) const {
|
||||
if (IntrID == 0)
|
||||
return false;
|
||||
|
||||
unsigned id = IntrID - Intrinsic::num_intrinsics + 1;
|
||||
#define GET_INTRINSIC_OVERLOAD_TABLE
|
||||
#include "MBlazeGenIntrinsics.inc"
|
||||
#undef GET_INTRINSIC_OVERLOAD_TABLE
|
||||
}
|
||||
|
||||
/// This defines the "getAttributes(LLVMContext &C, ID id)" method.
|
||||
#define GET_INTRINSIC_ATTRIBUTES
|
||||
#include "MBlazeGenIntrinsics.inc"
|
||||
#undef GET_INTRINSIC_ATTRIBUTES
|
||||
|
||||
static FunctionType *getType(LLVMContext &Context, unsigned id) {
|
||||
Type *ResultTy = NULL;
|
||||
SmallVector<Type*, 8> ArgTys;
|
||||
bool IsVarArg = false;
|
||||
|
||||
#define GET_INTRINSIC_GENERATOR
|
||||
#include "MBlazeGenIntrinsics.inc"
|
||||
#undef GET_INTRINSIC_GENERATOR
|
||||
|
||||
return FunctionType::get(ResultTy, ArgTys, IsVarArg);
|
||||
}
|
||||
|
||||
Function *MBlazeIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID,
|
||||
Type **Tys,
|
||||
unsigned numTy) const {
|
||||
assert(!isOverloaded(IntrID) && "MBlaze intrinsics are not overloaded");
|
||||
AttributeSet AList = getAttributes(M->getContext(),
|
||||
(mblazeIntrinsic::ID) IntrID);
|
||||
return cast<Function>(M->getOrInsertFunction(getName(IntrID),
|
||||
getType(M->getContext(), IntrID),
|
||||
AList));
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
//===-- MBlazeIntrinsicInfo.h - MBlaze Intrinsic 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 MBlaze implementation of TargetIntrinsicInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef MBLAZEINTRINSICS_H
|
||||
#define MBLAZEINTRINSICS_H
|
||||
|
||||
#include "llvm/Target/TargetIntrinsicInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MBlazeIntrinsicInfo : public TargetIntrinsicInfo {
|
||||
public:
|
||||
std::string getName(unsigned IntrID, Type **Tys = 0,
|
||||
unsigned numTys = 0) const;
|
||||
unsigned lookupName(const char *Name, unsigned Len) const;
|
||||
unsigned lookupGCCName(const char *Name) const;
|
||||
bool isOverloaded(unsigned IID) const;
|
||||
Function *getDeclaration(Module *M, unsigned ID, Type **Tys = 0,
|
||||
unsigned numTys = 0) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,131 +0,0 @@
|
||||
//===-- IntrinsicsMBlaze.td - Defines MBlaze intrinsics ----*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines all of the MicroBlaze-specific intrinsics.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Definitions for all MBlaze intrinsics.
|
||||
//
|
||||
|
||||
// MBlaze intrinsic classes.
|
||||
let TargetPrefix = "mblaze", isTarget = 1 in {
|
||||
class MBFSL_Get_Intrinsic : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
|
||||
|
||||
class MBFSL_Put_Intrinsic : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
|
||||
class MBFSL_PutT_Intrinsic : Intrinsic<[], [llvm_i32_ty], []>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MicroBlaze FSL Get Intrinsic Definitions.
|
||||
//
|
||||
|
||||
def int_mblaze_fsl_get : GCCBuiltin<"__builtin_mblaze_fsl_get">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_aget : GCCBuiltin<"__builtin_mblaze_fsl_aget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_cget : GCCBuiltin<"__builtin_mblaze_fsl_cget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_caget : GCCBuiltin<"__builtin_mblaze_fsl_caget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_eget : GCCBuiltin<"__builtin_mblaze_fsl_eget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_eaget : GCCBuiltin<"__builtin_mblaze_fsl_eaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_ecget : GCCBuiltin<"__builtin_mblaze_fsl_ecget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_ecaget : GCCBuiltin<"__builtin_mblaze_fsl_ecaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_nget : GCCBuiltin<"__builtin_mblaze_fsl_nget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_naget : GCCBuiltin<"__builtin_mblaze_fsl_naget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_ncget : GCCBuiltin<"__builtin_mblaze_fsl_ncget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_ncaget : GCCBuiltin<"__builtin_mblaze_fsl_ncaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_neget : GCCBuiltin<"__builtin_mblaze_fsl_neget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_neaget : GCCBuiltin<"__builtin_mblaze_fsl_neaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_necget : GCCBuiltin<"__builtin_mblaze_fsl_necget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_necaget : GCCBuiltin<"__builtin_mblaze_fsl_necaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tget : GCCBuiltin<"__builtin_mblaze_fsl_tget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_taget : GCCBuiltin<"__builtin_mblaze_fsl_taget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tcget : GCCBuiltin<"__builtin_mblaze_fsl_tcget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tcaget : GCCBuiltin<"__builtin_mblaze_fsl_tcaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_teget : GCCBuiltin<"__builtin_mblaze_fsl_teget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_teaget : GCCBuiltin<"__builtin_mblaze_fsl_teaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tecget : GCCBuiltin<"__builtin_mblaze_fsl_tecget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tecaget : GCCBuiltin<"__builtin_mblaze_fsl_tecaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tnget : GCCBuiltin<"__builtin_mblaze_fsl_tnget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tnaget : GCCBuiltin<"__builtin_mblaze_fsl_tnaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tncget : GCCBuiltin<"__builtin_mblaze_fsl_tncget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tncaget : GCCBuiltin<"__builtin_mblaze_fsl_tncaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tneget : GCCBuiltin<"__builtin_mblaze_fsl_tneget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tneaget : GCCBuiltin<"__builtin_mblaze_fsl_tneaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tnecget : GCCBuiltin<"__builtin_mblaze_fsl_tnecget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
def int_mblaze_fsl_tnecaget : GCCBuiltin<"__builtin_mblaze_fsl_tnecaget">,
|
||||
MBFSL_Get_Intrinsic;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MicroBlaze FSL Put Intrinsic Definitions.
|
||||
//
|
||||
|
||||
def int_mblaze_fsl_put : GCCBuiltin<"__builtin_mblaze_fsl_put">,
|
||||
MBFSL_Put_Intrinsic;
|
||||
def int_mblaze_fsl_aput : GCCBuiltin<"__builtin_mblaze_fsl_aput">,
|
||||
MBFSL_Put_Intrinsic;
|
||||
def int_mblaze_fsl_cput : GCCBuiltin<"__builtin_mblaze_fsl_cput">,
|
||||
MBFSL_Put_Intrinsic;
|
||||
def int_mblaze_fsl_caput : GCCBuiltin<"__builtin_mblaze_fsl_caput">,
|
||||
MBFSL_Put_Intrinsic;
|
||||
def int_mblaze_fsl_nput : GCCBuiltin<"__builtin_mblaze_fsl_nput">,
|
||||
MBFSL_Put_Intrinsic;
|
||||
def int_mblaze_fsl_naput : GCCBuiltin<"__builtin_mblaze_fsl_naput">,
|
||||
MBFSL_Put_Intrinsic;
|
||||
def int_mblaze_fsl_ncput : GCCBuiltin<"__builtin_mblaze_fsl_ncput">,
|
||||
MBFSL_Put_Intrinsic;
|
||||
def int_mblaze_fsl_ncaput : GCCBuiltin<"__builtin_mblaze_fsl_ncaput">,
|
||||
MBFSL_Put_Intrinsic;
|
||||
def int_mblaze_fsl_tput : GCCBuiltin<"__builtin_mblaze_fsl_tput">,
|
||||
MBFSL_PutT_Intrinsic;
|
||||
def int_mblaze_fsl_taput : GCCBuiltin<"__builtin_mblaze_fsl_taput">,
|
||||
MBFSL_PutT_Intrinsic;
|
||||
def int_mblaze_fsl_tcput : GCCBuiltin<"__builtin_mblaze_fsl_tcput">,
|
||||
MBFSL_PutT_Intrinsic;
|
||||
def int_mblaze_fsl_tcaput : GCCBuiltin<"__builtin_mblaze_fsl_tcaput">,
|
||||
MBFSL_PutT_Intrinsic;
|
||||
def int_mblaze_fsl_tnput : GCCBuiltin<"__builtin_mblaze_fsl_tnput">,
|
||||
MBFSL_PutT_Intrinsic;
|
||||
def int_mblaze_fsl_tnaput : GCCBuiltin<"__builtin_mblaze_fsl_tnaput">,
|
||||
MBFSL_PutT_Intrinsic;
|
||||
def int_mblaze_fsl_tncput : GCCBuiltin<"__builtin_mblaze_fsl_tncput">,
|
||||
MBFSL_PutT_Intrinsic;
|
||||
def int_mblaze_fsl_tncaput : GCCBuiltin<"__builtin_mblaze_fsl_tncaput">,
|
||||
MBFSL_PutT_Intrinsic;
|
@ -1,167 +0,0 @@
|
||||
//===-- MBlazeMCInstLower.cpp - Convert MBlaze 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 MBlaze MachineInstrs to their corresponding
|
||||
// MCInst records.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeMCInstLower.h"
|
||||
#include "MBlazeInstrInfo.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/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/Mangler.h"
|
||||
using namespace llvm;
|
||||
|
||||
MCSymbol *MBlazeMCInstLower::
|
||||
GetGlobalAddressSymbol(const MachineOperand &MO) const {
|
||||
switch (MO.getTargetFlags()) {
|
||||
default: llvm_unreachable("Unknown target flag on GV operand");
|
||||
case 0: break;
|
||||
}
|
||||
|
||||
return Printer.Mang->getSymbol(MO.getGlobal());
|
||||
}
|
||||
|
||||
MCSymbol *MBlazeMCInstLower::
|
||||
GetExternalSymbolSymbol(const MachineOperand &MO) const {
|
||||
switch (MO.getTargetFlags()) {
|
||||
default: llvm_unreachable("Unknown target flag on GV operand");
|
||||
case 0: break;
|
||||
}
|
||||
|
||||
return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
|
||||
}
|
||||
|
||||
MCSymbol *MBlazeMCInstLower::
|
||||
GetJumpTableSymbol(const MachineOperand &MO) const {
|
||||
SmallString<256> Name;
|
||||
raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI"
|
||||
<< Printer.getFunctionNumber() << '_'
|
||||
<< MO.getIndex();
|
||||
switch (MO.getTargetFlags()) {
|
||||
default: llvm_unreachable("Unknown target flag on GV operand");
|
||||
case 0: break;
|
||||
}
|
||||
|
||||
// Create a symbol for the name.
|
||||
return Ctx.GetOrCreateSymbol(Name.str());
|
||||
}
|
||||
|
||||
MCSymbol *MBlazeMCInstLower::
|
||||
GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
|
||||
SmallString<256> Name;
|
||||
raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI"
|
||||
<< Printer.getFunctionNumber() << '_'
|
||||
<< MO.getIndex();
|
||||
|
||||
switch (MO.getTargetFlags()) {
|
||||
default:
|
||||
llvm_unreachable("Unknown target flag on GV operand");
|
||||
|
||||
case 0: break;
|
||||
}
|
||||
|
||||
// Create a symbol for the name.
|
||||
return Ctx.GetOrCreateSymbol(Name.str());
|
||||
}
|
||||
|
||||
MCSymbol *MBlazeMCInstLower::
|
||||
GetBlockAddressSymbol(const MachineOperand &MO) const {
|
||||
switch (MO.getTargetFlags()) {
|
||||
default: llvm_unreachable("Unknown target flag on GV operand");
|
||||
case 0: break;
|
||||
}
|
||||
|
||||
return Printer.GetBlockAddressSymbol(MO.getBlockAddress());
|
||||
}
|
||||
|
||||
MCOperand MBlazeMCInstLower::
|
||||
LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const {
|
||||
// FIXME: We would like an efficient form for this, so we don't have to do a
|
||||
// lot of extra uniquing.
|
||||
const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
|
||||
|
||||
switch (MO.getTargetFlags()) {
|
||||
default:
|
||||
llvm_unreachable("Unknown target flag on GV operand");
|
||||
|
||||
case 0: break;
|
||||
}
|
||||
|
||||
if (!MO.isJTI() && MO.getOffset())
|
||||
Expr = MCBinaryExpr::CreateAdd(Expr,
|
||||
MCConstantExpr::Create(MO.getOffset(), Ctx),
|
||||
Ctx);
|
||||
return MCOperand::CreateExpr(Expr);
|
||||
}
|
||||
|
||||
void MBlazeMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
|
||||
OutMI.setOpcode(MI->getOpcode());
|
||||
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand &MO = MI->getOperand(i);
|
||||
|
||||
MCOperand MCOp;
|
||||
switch (MO.getType()) {
|
||||
default: llvm_unreachable("unknown operand type");
|
||||
case MachineOperand::MO_Register:
|
||||
// Ignore all implicit register operands.
|
||||
if (MO.isImplicit()) continue;
|
||||
MCOp = MCOperand::CreateReg(MO.getReg());
|
||||
break;
|
||||
case MachineOperand::MO_Immediate:
|
||||
MCOp = MCOperand::CreateImm(MO.getImm());
|
||||
break;
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
|
||||
MO.getMBB()->getSymbol(), Ctx));
|
||||
break;
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
|
||||
break;
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
|
||||
break;
|
||||
case MachineOperand::MO_JumpTableIndex:
|
||||
MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
|
||||
break;
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
|
||||
break;
|
||||
case MachineOperand::MO_BlockAddress:
|
||||
MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO));
|
||||
break;
|
||||
case MachineOperand::MO_FPImmediate: {
|
||||
bool ignored;
|
||||
APFloat FVal = MO.getFPImm()->getValueAPF();
|
||||
FVal.convert(APFloat::IEEEsingle, APFloat::rmTowardZero, &ignored);
|
||||
|
||||
APInt IVal = FVal.bitcastToAPInt();
|
||||
uint64_t Val = *IVal.getRawData();
|
||||
MCOp = MCOperand::CreateImm(Val);
|
||||
break;
|
||||
}
|
||||
case MachineOperand::MO_RegisterMask:
|
||||
continue;
|
||||
}
|
||||
|
||||
OutMI.addOperand(MCOp);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
//===-- MBlazeMCInstLower.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 MBLAZE_MCINSTLOWER_H
|
||||
#define MBLAZE_MCINSTLOWER_H
|
||||
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
class AsmPrinter;
|
||||
class MCContext;
|
||||
class MCInst;
|
||||
class MCOperand;
|
||||
class MCSymbol;
|
||||
class MachineInstr;
|
||||
class MachineModuleInfoMachO;
|
||||
class MachineOperand;
|
||||
|
||||
/// MBlazeMCInstLower - This class is used to lower an MachineInstr
|
||||
/// into an MCInst.
|
||||
class LLVM_LIBRARY_VISIBILITY MBlazeMCInstLower {
|
||||
MCContext &Ctx;
|
||||
|
||||
AsmPrinter &Printer;
|
||||
public:
|
||||
MBlazeMCInstLower(MCContext &ctx, AsmPrinter &printer)
|
||||
: Ctx(ctx), Printer(printer) {}
|
||||
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
|
||||
|
||||
MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
|
||||
|
||||
MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetBlockAddressSymbol(const MachineOperand &MO) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,14 +0,0 @@
|
||||
//===-- MBlazeMachineFunctionInfo.cpp - Private data ----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeMachineFunction.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void MBlazeFunctionInfo::anchor() { }
|
@ -1,169 +0,0 @@
|
||||
//===-- MBlazeMachineFunctionInfo.h - Private data --------------*- 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 MBlaze specific subclass of MachineFunctionInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZE_MACHINE_FUNCTION_INFO_H
|
||||
#define MBLAZE_MACHINE_FUNCTION_INFO_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// MBlazeFunctionInfo - This class is derived from MachineFunction private
|
||||
/// MBlaze target-specific information for each MachineFunction.
|
||||
class MBlazeFunctionInfo : public MachineFunctionInfo {
|
||||
virtual void anchor();
|
||||
|
||||
/// Holds for each function where on the stack the Frame Pointer must be
|
||||
/// saved. This is used on Prologue and Epilogue to emit FP save/restore
|
||||
int FPStackOffset;
|
||||
|
||||
/// Holds for each function where on the stack the Return Address must be
|
||||
/// saved. This is used on Prologue and Epilogue to emit RA save/restore
|
||||
int RAStackOffset;
|
||||
|
||||
/// MBlazeFIHolder - Holds a FrameIndex and it's Stack Pointer Offset
|
||||
struct MBlazeFIHolder {
|
||||
|
||||
int FI;
|
||||
int SPOffset;
|
||||
|
||||
MBlazeFIHolder(int FrameIndex, int StackPointerOffset)
|
||||
: FI(FrameIndex), SPOffset(StackPointerOffset) {}
|
||||
};
|
||||
|
||||
/// When PIC is used the GP must be saved on the stack on the function
|
||||
/// prologue and must be reloaded from this stack location after every
|
||||
/// call. A reference to its stack location and frame index must be kept
|
||||
/// to be used on emitPrologue and processFunctionBeforeFrameFinalized.
|
||||
MBlazeFIHolder GPHolder;
|
||||
|
||||
/// On LowerFormalArguments the stack size is unknown, so the Stack
|
||||
/// Pointer Offset calculation of "not in register arguments" must be
|
||||
/// postponed to emitPrologue.
|
||||
SmallVector<MBlazeFIHolder, 16> FnLoadArgs;
|
||||
bool HasLoadArgs;
|
||||
|
||||
// When VarArgs, we must write registers back to caller stack, preserving
|
||||
// on register arguments. Since the stack size is unknown on
|
||||
// LowerFormalArguments, the Stack Pointer Offset calculation must be
|
||||
// postponed to emitPrologue.
|
||||
SmallVector<MBlazeFIHolder, 4> FnStoreVarArgs;
|
||||
bool HasStoreVarArgs;
|
||||
|
||||
// When determining the final stack layout some of the frame indexes may
|
||||
// be replaced by new frame indexes that reside in the caller's stack
|
||||
// frame. The replacements are recorded in this structure.
|
||||
DenseMap<int,int> FIReplacements;
|
||||
|
||||
/// SRetReturnReg - Some subtargets 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;
|
||||
|
||||
/// LiveInFI - keeps track of the frame indexes in a callers stack
|
||||
/// frame that are live into a function.
|
||||
SmallVector<int, 16> LiveInFI;
|
||||
|
||||
public:
|
||||
MBlazeFunctionInfo(MachineFunction& MF)
|
||||
: FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1), HasLoadArgs(false),
|
||||
HasStoreVarArgs(false), SRetReturnReg(0), GlobalBaseReg(0),
|
||||
VarArgsFrameIndex(0), LiveInFI()
|
||||
{}
|
||||
|
||||
int getFPStackOffset() const { return FPStackOffset; }
|
||||
void setFPStackOffset(int Off) { FPStackOffset = Off; }
|
||||
|
||||
int getRAStackOffset() const { return RAStackOffset; }
|
||||
void setRAStackOffset(int Off) { RAStackOffset = Off; }
|
||||
|
||||
int getGPStackOffset() const { return GPHolder.SPOffset; }
|
||||
int getGPFI() const { return GPHolder.FI; }
|
||||
void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; }
|
||||
void setGPFI(int FI) { GPHolder.FI = FI; }
|
||||
bool needGPSaveRestore() const { return GPHolder.SPOffset != -1; }
|
||||
|
||||
bool hasLoadArgs() const { return HasLoadArgs; }
|
||||
bool hasStoreVarArgs() const { return HasStoreVarArgs; }
|
||||
|
||||
void recordLiveIn(int FI) {
|
||||
LiveInFI.push_back(FI);
|
||||
}
|
||||
|
||||
bool isLiveIn(int FI) {
|
||||
for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i)
|
||||
if (FI == LiveInFI[i]) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const SmallVectorImpl<int> &getLiveIn() const { return LiveInFI; }
|
||||
|
||||
void recordReplacement(int OFI, int NFI) {
|
||||
FIReplacements.insert(std::make_pair(OFI,NFI));
|
||||
}
|
||||
|
||||
bool hasReplacement(int OFI) const {
|
||||
return FIReplacements.find(OFI) != FIReplacements.end();
|
||||
}
|
||||
|
||||
int getReplacement(int OFI) const {
|
||||
return FIReplacements.lookup(OFI);
|
||||
}
|
||||
|
||||
void recordLoadArgsFI(int FI, int SPOffset) {
|
||||
if (!HasLoadArgs) HasLoadArgs=true;
|
||||
FnLoadArgs.push_back(MBlazeFIHolder(FI, SPOffset));
|
||||
}
|
||||
|
||||
void recordStoreVarArgsFI(int FI, int SPOffset) {
|
||||
if (!HasStoreVarArgs) HasStoreVarArgs=true;
|
||||
FnStoreVarArgs.push_back(MBlazeFIHolder(FI, SPOffset));
|
||||
}
|
||||
|
||||
void adjustLoadArgsFI(MachineFrameInfo *MFI) const {
|
||||
if (!hasLoadArgs()) return;
|
||||
for (unsigned i = 0, e = FnLoadArgs.size(); i != e; ++i)
|
||||
MFI->setObjectOffset(FnLoadArgs[i].FI, FnLoadArgs[i].SPOffset);
|
||||
}
|
||||
|
||||
void adjustStoreVarArgsFI(MachineFrameInfo *MFI) const {
|
||||
if (!hasStoreVarArgs()) return;
|
||||
for (unsigned i = 0, e = FnStoreVarArgs.size(); i != e; ++i)
|
||||
MFI->setObjectOffset(FnStoreVarArgs[i].FI, FnStoreVarArgs[i].SPOffset);
|
||||
}
|
||||
|
||||
unsigned getSRetReturnReg() const { return SRetReturnReg; }
|
||||
void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
|
||||
|
||||
unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
|
||||
void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
|
||||
|
||||
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
|
||||
void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
|
||||
};
|
||||
|
||||
} // end of namespace llvm
|
||||
|
||||
#endif // MBLAZE_MACHINE_FUNCTION_INFO_H
|
@ -1,145 +0,0 @@
|
||||
//===-- MBlazeRegisterInfo.cpp - MBlaze Register 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 MBlaze implementation of the TargetRegisterInfo
|
||||
// class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "mblaze-frame-info"
|
||||
|
||||
#include "MBlazeRegisterInfo.h"
|
||||
#include "MBlaze.h"
|
||||
#include "MBlazeMachineFunction.h"
|
||||
#include "MBlazeSubtarget.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/ValueTypes.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
|
||||
#define GET_REGINFO_TARGET_DESC
|
||||
#include "MBlazeGenRegisterInfo.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MBlazeRegisterInfo::
|
||||
MBlazeRegisterInfo(const MBlazeSubtarget &ST)
|
||||
: MBlazeGenRegisterInfo(MBlaze::R15), Subtarget(ST) {}
|
||||
|
||||
unsigned MBlazeRegisterInfo::getPICCallReg() {
|
||||
return MBlaze::R20;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Callee Saved Registers methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// MBlaze Callee Saved Registers
|
||||
const uint16_t* MBlazeRegisterInfo::
|
||||
getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
// MBlaze callee-save register range is R20 - R31
|
||||
static const uint16_t CalleeSavedRegs[] = {
|
||||
MBlaze::R20, MBlaze::R21, MBlaze::R22, MBlaze::R23,
|
||||
MBlaze::R24, MBlaze::R25, MBlaze::R26, MBlaze::R27,
|
||||
MBlaze::R28, MBlaze::R29, MBlaze::R30, MBlaze::R31,
|
||||
0
|
||||
};
|
||||
|
||||
return CalleeSavedRegs;
|
||||
}
|
||||
|
||||
BitVector MBlazeRegisterInfo::
|
||||
getReservedRegs(const MachineFunction &MF) const {
|
||||
BitVector Reserved(getNumRegs());
|
||||
Reserved.set(MBlaze::R0);
|
||||
Reserved.set(MBlaze::R1);
|
||||
Reserved.set(MBlaze::R2);
|
||||
Reserved.set(MBlaze::R13);
|
||||
Reserved.set(MBlaze::R14);
|
||||
Reserved.set(MBlaze::R15);
|
||||
Reserved.set(MBlaze::R16);
|
||||
Reserved.set(MBlaze::R17);
|
||||
Reserved.set(MBlaze::R18);
|
||||
Reserved.set(MBlaze::R19);
|
||||
return Reserved;
|
||||
}
|
||||
|
||||
// FrameIndex represent objects inside a abstract stack.
|
||||
// We must replace FrameIndex with an stack/frame pointer
|
||||
// direct reference.
|
||||
void MBlazeRegisterInfo::
|
||||
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
unsigned FIOperandNum, RegScavenger *RS) const {
|
||||
MachineInstr &MI = *II;
|
||||
MachineFunction &MF = *MI.getParent()->getParent();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
unsigned OFIOperandNum = FIOperandNum == 2 ? 1 : 2;
|
||||
|
||||
DEBUG(dbgs() << "\nFunction : " << MF.getName() << "\n";
|
||||
dbgs() << "<--------->\n" << MI);
|
||||
|
||||
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
|
||||
int stackSize = MFI->getStackSize();
|
||||
int spOffset = MFI->getObjectOffset(FrameIndex);
|
||||
|
||||
DEBUG(MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
dbgs() << "FrameIndex : " << FrameIndex << "\n"
|
||||
<< "spOffset : " << spOffset << "\n"
|
||||
<< "stackSize : " << stackSize << "\n"
|
||||
<< "isFixed : " << MFI->isFixedObjectIndex(FrameIndex) << "\n"
|
||||
<< "isLiveIn : " << MBlazeFI->isLiveIn(FrameIndex) << "\n"
|
||||
<< "isSpill : " << MFI->isSpillSlotObjectIndex(FrameIndex)
|
||||
<< "\n" );
|
||||
|
||||
// as explained on LowerFormalArguments, detect negative offsets
|
||||
// and adjust SPOffsets considering the final stack size.
|
||||
int Offset = (spOffset < 0) ? (stackSize - spOffset) : spOffset;
|
||||
Offset += MI.getOperand(OFIOperandNum).getImm();
|
||||
|
||||
DEBUG(dbgs() << "Offset : " << Offset << "\n" << "<--------->\n");
|
||||
|
||||
MI.getOperand(OFIOperandNum).ChangeToImmediate(Offset);
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(getFrameRegister(MF), false);
|
||||
}
|
||||
|
||||
void MBlazeRegisterInfo::
|
||||
processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *) const {
|
||||
// Set the stack offset where GP must be saved/loaded from.
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
|
||||
if (MBlazeFI->needGPSaveRestore())
|
||||
MFI->setObjectOffset(MBlazeFI->getGPFI(), MBlazeFI->getGPStackOffset());
|
||||
}
|
||||
|
||||
unsigned MBlazeRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
||||
|
||||
return TFI->hasFP(MF) ? MBlaze::R19 : MBlaze::R1;
|
||||
}
|
||||
|
||||
unsigned MBlazeRegisterInfo::getEHExceptionRegister() const {
|
||||
llvm_unreachable("What is the exception register");
|
||||
}
|
||||
|
||||
unsigned MBlazeRegisterInfo::getEHHandlerRegister() const {
|
||||
llvm_unreachable("What is the exception handler register");
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
//===-- MBlazeRegisterInfo.h - MBlaze 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 MBlaze implementation of the TargetRegisterInfo
|
||||
// class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZEREGISTERINFO_H
|
||||
#define MBLAZEREGISTERINFO_H
|
||||
|
||||
#include "MBlaze.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
|
||||
#define GET_REGINFO_HEADER
|
||||
#include "MBlazeGenRegisterInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
class MBlazeSubtarget;
|
||||
class TargetInstrInfo;
|
||||
class Type;
|
||||
|
||||
namespace MBlaze {
|
||||
/// SubregIndex - The index of various sized subregister classes. Note that
|
||||
/// these indices must be kept in sync with the class indices in the
|
||||
/// MBlazeRegisterInfo.td file.
|
||||
enum SubregIndex {
|
||||
SUBREG_FPEVEN = 1, SUBREG_FPODD = 2
|
||||
};
|
||||
}
|
||||
|
||||
struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo {
|
||||
const MBlazeSubtarget &Subtarget;
|
||||
|
||||
MBlazeRegisterInfo(const MBlazeSubtarget &Subtarget);
|
||||
|
||||
/// Get PIC indirect call register
|
||||
static unsigned getPICCallReg();
|
||||
|
||||
/// Code Generation virtual methods...
|
||||
const uint16_t *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
/// Stack Frame Processing Methods
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, unsigned FIOperandNum,
|
||||
RegScavenger *RS = NULL) const;
|
||||
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF,
|
||||
RegScavenger *RS = NULL) const;
|
||||
|
||||
/// Debug information queries.
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||
|
||||
/// Exception handling queries.
|
||||
unsigned getEHExceptionRegister() const;
|
||||
unsigned getEHHandlerRegister() const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -1,148 +0,0 @@
|
||||
//===-- MBlazeRegisterInfo.td - MBlaze 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 MicroBlaze register file
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// We have banks of 32 registers each.
|
||||
class MBlazeReg<string n> : Register<n> {
|
||||
field bits<5> Num;
|
||||
let Namespace = "MBlaze";
|
||||
}
|
||||
|
||||
// Special purpose registers have 15-bit values
|
||||
class MBlazeSReg<string n> : Register<n> {
|
||||
field bits<15> Num;
|
||||
let Namespace = "MBlaze";
|
||||
}
|
||||
|
||||
// MBlaze general purpose registers
|
||||
class MBlazeGPRReg<bits<5> num, string n> : MBlazeReg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
|
||||
// MBlaze special purpose registers
|
||||
class MBlazeSPRReg<bits<15> num, string n> : MBlazeSReg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Registers
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Namespace = "MBlaze" in {
|
||||
// General Purpose Registers
|
||||
def R0 : MBlazeGPRReg< 0, "r0">, DwarfRegNum<[0]>;
|
||||
def R1 : MBlazeGPRReg< 1, "r1">, DwarfRegNum<[1]>;
|
||||
def R2 : MBlazeGPRReg< 2, "r2">, DwarfRegNum<[2]>;
|
||||
def R3 : MBlazeGPRReg< 3, "r3">, DwarfRegNum<[3]>;
|
||||
def R4 : MBlazeGPRReg< 4, "r4">, DwarfRegNum<[4]>;
|
||||
def R5 : MBlazeGPRReg< 5, "r5">, DwarfRegNum<[5]>;
|
||||
def R6 : MBlazeGPRReg< 6, "r6">, DwarfRegNum<[6]>;
|
||||
def R7 : MBlazeGPRReg< 7, "r7">, DwarfRegNum<[7]>;
|
||||
def R8 : MBlazeGPRReg< 8, "r8">, DwarfRegNum<[8]>;
|
||||
def R9 : MBlazeGPRReg< 9, "r9">, DwarfRegNum<[9]>;
|
||||
def R10 : MBlazeGPRReg< 10, "r10">, DwarfRegNum<[10]>;
|
||||
def R11 : MBlazeGPRReg< 11, "r11">, DwarfRegNum<[11]>;
|
||||
def R12 : MBlazeGPRReg< 12, "r12">, DwarfRegNum<[12]>;
|
||||
def R13 : MBlazeGPRReg< 13, "r13">, DwarfRegNum<[13]>;
|
||||
def R14 : MBlazeGPRReg< 14, "r14">, DwarfRegNum<[14]>;
|
||||
def R15 : MBlazeGPRReg< 15, "r15">, DwarfRegNum<[15]>;
|
||||
def R16 : MBlazeGPRReg< 16, "r16">, DwarfRegNum<[16]>;
|
||||
def R17 : MBlazeGPRReg< 17, "r17">, DwarfRegNum<[17]>;
|
||||
def R18 : MBlazeGPRReg< 18, "r18">, DwarfRegNum<[18]>;
|
||||
def R19 : MBlazeGPRReg< 19, "r19">, DwarfRegNum<[19]>;
|
||||
def R20 : MBlazeGPRReg< 20, "r20">, DwarfRegNum<[20]>;
|
||||
def R21 : MBlazeGPRReg< 21, "r21">, DwarfRegNum<[21]>;
|
||||
def R22 : MBlazeGPRReg< 22, "r22">, DwarfRegNum<[22]>;
|
||||
def R23 : MBlazeGPRReg< 23, "r23">, DwarfRegNum<[23]>;
|
||||
def R24 : MBlazeGPRReg< 24, "r24">, DwarfRegNum<[24]>;
|
||||
def R25 : MBlazeGPRReg< 25, "r25">, DwarfRegNum<[25]>;
|
||||
def R26 : MBlazeGPRReg< 26, "r26">, DwarfRegNum<[26]>;
|
||||
def R27 : MBlazeGPRReg< 27, "r27">, DwarfRegNum<[27]>;
|
||||
def R28 : MBlazeGPRReg< 28, "r28">, DwarfRegNum<[28]>;
|
||||
def R29 : MBlazeGPRReg< 29, "r29">, DwarfRegNum<[29]>;
|
||||
def R30 : MBlazeGPRReg< 30, "r30">, DwarfRegNum<[30]>;
|
||||
def R31 : MBlazeGPRReg< 31, "r31">, DwarfRegNum<[31]>;
|
||||
|
||||
// Special Purpose Registers
|
||||
def RPC : MBlazeSPRReg<0x0000, "rpc">, DwarfRegNum<[32]>;
|
||||
def RMSR : MBlazeSPRReg<0x0001, "rmsr">, DwarfRegNum<[33]>;
|
||||
def REAR : MBlazeSPRReg<0x0003, "rear">, DwarfRegNum<[34]>;
|
||||
def RESR : MBlazeSPRReg<0x0005, "resr">, DwarfRegNum<[35]>;
|
||||
def RFSR : MBlazeSPRReg<0x0007, "rfsr">, DwarfRegNum<[36]>;
|
||||
def RBTR : MBlazeSPRReg<0x000B, "rbtr">, DwarfRegNum<[37]>;
|
||||
def REDR : MBlazeSPRReg<0x000D, "redr">, DwarfRegNum<[38]>;
|
||||
def RPID : MBlazeSPRReg<0x1000, "rpid">, DwarfRegNum<[39]>;
|
||||
def RZPR : MBlazeSPRReg<0x1001, "rzpr">, DwarfRegNum<[40]>;
|
||||
def RTLBX : MBlazeSPRReg<0x1002, "rtlbx">, DwarfRegNum<[41]>;
|
||||
def RTLBLO : MBlazeSPRReg<0x1003, "rtlblo">, DwarfRegNum<[42]>;
|
||||
def RTLBHI : MBlazeSPRReg<0x1004, "rtlbhi">, DwarfRegNum<[43]>;
|
||||
def RTLBSX : MBlazeSPRReg<0x1004, "rtlbsx">, DwarfRegNum<[44]>;
|
||||
def RPVR0 : MBlazeSPRReg<0x2000, "rpvr0">, DwarfRegNum<[45]>;
|
||||
def RPVR1 : MBlazeSPRReg<0x2001, "rpvr1">, DwarfRegNum<[46]>;
|
||||
def RPVR2 : MBlazeSPRReg<0x2002, "rpvr2">, DwarfRegNum<[47]>;
|
||||
def RPVR3 : MBlazeSPRReg<0x2003, "rpvr3">, DwarfRegNum<[48]>;
|
||||
def RPVR4 : MBlazeSPRReg<0x2004, "rpvr4">, DwarfRegNum<[49]>;
|
||||
def RPVR5 : MBlazeSPRReg<0x2005, "rpvr5">, DwarfRegNum<[50]>;
|
||||
def RPVR6 : MBlazeSPRReg<0x2006, "rpvr6">, DwarfRegNum<[51]>;
|
||||
def RPVR7 : MBlazeSPRReg<0x2007, "rpvr7">, DwarfRegNum<[52]>;
|
||||
def RPVR8 : MBlazeSPRReg<0x2008, "rpvr8">, DwarfRegNum<[53]>;
|
||||
def RPVR9 : MBlazeSPRReg<0x2009, "rpvr9">, DwarfRegNum<[54]>;
|
||||
def RPVR10 : MBlazeSPRReg<0x200A, "rpvr10">, DwarfRegNum<[55]>;
|
||||
def RPVR11 : MBlazeSPRReg<0x200B, "rpvr11">, DwarfRegNum<[56]>;
|
||||
|
||||
// The carry bit. In the Microblaze this is really bit 29 of the
|
||||
// MSR register but this is the only bit of that register that we
|
||||
// are interested in modeling.
|
||||
def CARRY : MBlazeSPRReg<0x0000, "rmsr[c]">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register Classes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def GPR : RegisterClass<"MBlaze", [i32,f32], 32, (sequence "R%u", 0, 31)>;
|
||||
|
||||
def SPR : RegisterClass<"MBlaze", [i32], 32, (add
|
||||
// Reserved
|
||||
RPC,
|
||||
RMSR,
|
||||
REAR,
|
||||
RESR,
|
||||
RFSR,
|
||||
RBTR,
|
||||
REDR,
|
||||
RPID,
|
||||
RZPR,
|
||||
RTLBX,
|
||||
RTLBLO,
|
||||
RTLBHI,
|
||||
RPVR0,
|
||||
RPVR1,
|
||||
RPVR2,
|
||||
RPVR3,
|
||||
RPVR4,
|
||||
RPVR5,
|
||||
RPVR6,
|
||||
RPVR7,
|
||||
RPVR8,
|
||||
RPVR9,
|
||||
RPVR10,
|
||||
RPVR11
|
||||
)>
|
||||
{
|
||||
// None of the special purpose registers are allocatable.
|
||||
let isAllocatable = 0;
|
||||
}
|
||||
|
||||
def CRC : RegisterClass<"MBlaze", [i32], 32, (add CARRY)> {
|
||||
let CopyCost = -1;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
//===-- MBlazeRelocations.h - MBlaze Code Relocations -----------*- 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 MBlaze target-specific relocation types.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZERELOCATIONS_H
|
||||
#define MBLAZERELOCATIONS_H
|
||||
|
||||
#include "llvm/CodeGen/MachineRelocation.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace MBlaze {
|
||||
enum RelocationType {
|
||||
/// reloc_pcrel_word - PC relative relocation, add the relocated value to
|
||||
/// the value already in memory, after we adjust it for where the PC is.
|
||||
reloc_pcrel_word = 0,
|
||||
|
||||
/// reloc_picrel_word - PIC base relative relocation, add the relocated
|
||||
/// value to the value already in memory, after we adjust it for where the
|
||||
/// PIC base is.
|
||||
reloc_picrel_word = 1,
|
||||
|
||||
/// reloc_absolute_word - absolute relocation, just add the relocated
|
||||
/// value to the value already in memory.
|
||||
reloc_absolute_word = 2,
|
||||
|
||||
/// reloc_absolute_word_sext - absolute relocation, just add the relocated
|
||||
/// value to the value already in memory. In object files, it represents a
|
||||
/// value which must be sign-extended when resolving the relocation.
|
||||
reloc_absolute_word_sext = 3,
|
||||
|
||||
/// reloc_absolute_dword - absolute relocation, just add the relocated
|
||||
/// value to the value already in memory.
|
||||
reloc_absolute_dword = 4
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,50 +0,0 @@
|
||||
//===-- MBlazeSchedule.td - MBlaze Scheduling Definitions --*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze functional units.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def IF : FuncUnit;
|
||||
def ID : FuncUnit;
|
||||
def EX : FuncUnit;
|
||||
def MA : FuncUnit;
|
||||
def WB : FuncUnit;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Itinerary classes used for MBlaze
|
||||
//===----------------------------------------------------------------------===//
|
||||
def IIC_ALU : InstrItinClass;
|
||||
def IIC_ALUm : InstrItinClass;
|
||||
def IIC_ALUd : InstrItinClass;
|
||||
def IIC_SHT : InstrItinClass;
|
||||
def IIC_FSLg : InstrItinClass;
|
||||
def IIC_FSLp : InstrItinClass;
|
||||
def IIC_MEMs : InstrItinClass;
|
||||
def IIC_MEMl : InstrItinClass;
|
||||
def IIC_FPU : InstrItinClass;
|
||||
def IIC_FPUd : InstrItinClass;
|
||||
def IIC_FPUf : InstrItinClass;
|
||||
def IIC_FPUi : InstrItinClass;
|
||||
def IIC_FPUs : InstrItinClass;
|
||||
def IIC_FPUc : InstrItinClass;
|
||||
def IIC_BR : InstrItinClass;
|
||||
def IIC_BRc : InstrItinClass;
|
||||
def IIC_BRl : InstrItinClass;
|
||||
def IIC_WDC : InstrItinClass;
|
||||
def IIC_Pseudo : InstrItinClass;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze instruction itineraries for three stage pipeline.
|
||||
//===----------------------------------------------------------------------===//
|
||||
include "MBlazeSchedule3.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze instruction itineraries for five stage pipeline.
|
||||
//===----------------------------------------------------------------------===//
|
||||
include "MBlazeSchedule5.td"
|
@ -1,236 +0,0 @@
|
||||
//===-- MBlazeSchedule3.td - MBlaze Scheduling Definitions -*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze instruction itineraries for the three stage pipeline.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def MBlazePipe3Itineraries : ProcessorItineraries<
|
||||
[IF,ID,EX], [], [
|
||||
|
||||
// ALU instruction with one destination register and either two register
|
||||
// source operands or one register source operand and one immediate operand.
|
||||
// The instruction takes one cycle to execute in each of the stages. The
|
||||
// two source operands are read during the decode stage and the result is
|
||||
// ready after the execute stage.
|
||||
InstrItinData< IIC_ALU,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]>], // one cycle in execute stage
|
||||
[ 2 // result ready after two cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// ALU multiply instruction with one destination register and either two
|
||||
// register source operands or one register source operand and one immediate
|
||||
// operand. The instruction takes one cycle to execute in each of the
|
||||
// pipeline stages except the execute stage, which takes three cycles. The
|
||||
// two source operands are read during the decode stage and the result is
|
||||
// ready after the execute stage.
|
||||
InstrItinData< IIC_ALUm,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<3,[EX]>], // three cycles in execute stage
|
||||
[ 4 // result ready after four cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// ALU divide instruction with one destination register two register source
|
||||
// operands. The instruction takes one cycle to execute in each the pipeline
|
||||
// stages except the execute stage, which takes 34 cycles. The two
|
||||
// source operands are read during the decode stage and the result is ready
|
||||
// after the execute stage.
|
||||
InstrItinData< IIC_ALUd,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<34,[EX]>], // 34 cycles in execute stage
|
||||
[ 35 // result ready after 35 cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Shift instruction with one destination register and either two register
|
||||
// source operands or one register source operand and one immediate operand.
|
||||
// The instruction takes one cycle to execute in each of the pipeline stages
|
||||
// except the execute stage, which takes two cycles. The two source operands
|
||||
// are read during the decode stage and the result is ready after the execute
|
||||
// stage.
|
||||
InstrItinData< IIC_SHT,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<2,[EX]>], // two cycles in execute stage
|
||||
[ 3 // result ready after three cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Branch instruction with one source operand register. The instruction takes
|
||||
// one cycle to execute in each of the pipeline stages. The source operand is
|
||||
// read during the decode stage.
|
||||
InstrItinData< IIC_BR,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]>], // one cycle in execute stage
|
||||
[ 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Conditional branch instruction with two source operand registers. The
|
||||
// instruction takes one cycle to execute in each of the pipeline stages. The
|
||||
// two source operands are read during the decode stage.
|
||||
InstrItinData< IIC_BRc,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]>], // one cycle in execute stage
|
||||
[ 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Branch and link instruction with one destination register and one source
|
||||
// operand register. The instruction takes one cycle to execute in each of
|
||||
// the pipeline stages. The source operand is read during the decode stage
|
||||
// and the destination register is ready after the execute stage.
|
||||
InstrItinData< IIC_BRl,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]>], // one cycle in execute stage
|
||||
[ 2 // result ready after two cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Cache control instruction with two source operand registers. The
|
||||
// instruction takes one cycle to execute in each of the pipeline stages
|
||||
// except the memory access stage, which takes two cycles. The source
|
||||
// operands are read during the decode stage.
|
||||
InstrItinData< IIC_WDC,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<2,[EX]>], // two cycles in execute stage
|
||||
[ 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Floating point instruction with one destination register and two source
|
||||
// operand registers. The instruction takes one cycle to execute in each of
|
||||
// the pipeline stages except the execute stage, which takes six cycles. The
|
||||
// source operands are read during the decode stage and the results are ready
|
||||
// after the execute stage.
|
||||
InstrItinData< IIC_FPU,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<6,[EX]>], // six cycles in execute stage
|
||||
[ 7 // result ready after seven cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Floating point divide instruction with one destination register and two
|
||||
// source operand registers. The instruction takes one cycle to execute in
|
||||
// each of the pipeline stages except the execute stage, which takes 30
|
||||
// cycles. The source operands are read during the decode stage and the
|
||||
// results are ready after the execute stage.
|
||||
InstrItinData< IIC_FPUd,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<30,[EX]>], // one cycle in execute stage
|
||||
[ 31 // result ready after 31 cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Convert floating point to integer instruction with one destination
|
||||
// register and one source operand register. The instruction takes one cycle
|
||||
// to execute in each of the pipeline stages except the execute stage,
|
||||
// which takes seven cycles. The source operands are read during the decode
|
||||
// stage and the results are ready after the execute stage.
|
||||
InstrItinData< IIC_FPUi,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<7,[EX]>], // seven cycles in execute stage
|
||||
[ 8 // result ready after eight cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Convert integer to floating point instruction with one destination
|
||||
// register and one source operand register. The instruction takes one cycle
|
||||
// to execute in each of the pipeline stages except the execute stage,
|
||||
// which takes six cycles. The source operands are read during the decode
|
||||
// stage and the results are ready after the execute stage.
|
||||
InstrItinData< IIC_FPUf,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<6,[EX]>], // six cycles in execute stage
|
||||
[ 7 // result ready after seven cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Floating point square root instruction with one destination register and
|
||||
// one source operand register. The instruction takes one cycle to execute in
|
||||
// each of the pipeline stages except the execute stage, which takes 29
|
||||
// cycles. The source operands are read during the decode stage and the
|
||||
// results are ready after the execute stage.
|
||||
InstrItinData< IIC_FPUs,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<29,[EX]>], // 29 cycles in execute stage
|
||||
[ 30 // result ready after 30 cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Floating point comparison instruction with one destination register and
|
||||
// two source operand registers. The instruction takes one cycle to execute
|
||||
// in each of the pipeline stages except the execute stage, which takes three
|
||||
// cycles. The source operands are read during the decode stage and the
|
||||
// results are ready after the execute stage.
|
||||
InstrItinData< IIC_FPUc,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<3,[EX]>], // three cycles in execute stage
|
||||
[ 4 // result ready after four cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// FSL get instruction with one register or immediate source operand and one
|
||||
// destination register. The instruction takes one cycle to execute in each
|
||||
// of the pipeline stages except the execute stage, which takes two cycles.
|
||||
// The one source operand is read during the decode stage and the result is
|
||||
// ready after the execute stage.
|
||||
InstrItinData< IIC_FSLg,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<2,[EX]>], // two cycles in execute stage
|
||||
[ 3 // result ready after two cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// FSL put instruction with either two register source operands or one
|
||||
// register source operand and one immediate operand. There is no result
|
||||
// produced by the instruction. The instruction takes one cycle to execute in
|
||||
// each of the pipeline stages except the execute stage, which takes two
|
||||
// cycles. The two source operands are read during the decode stage.
|
||||
InstrItinData< IIC_FSLp,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<2,[EX]>], // two cycles in execute stage
|
||||
[ 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Memory store instruction with either three register source operands or two
|
||||
// register source operands and one immediate operand. There is no result
|
||||
// produced by the instruction. The instruction takes one cycle to execute in
|
||||
// each of the pipeline stages except the execute stage, which takes two
|
||||
// cycles. All of the source operands are read during the decode stage.
|
||||
InstrItinData< IIC_MEMs,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<2,[EX]>], // two cycles in execute stage
|
||||
[ 1 // first operand read after one cycle
|
||||
, 1 // second operand read after one cycle
|
||||
, 1 ]>, // third operand read after one cycle
|
||||
|
||||
// Memory load instruction with one destination register and either two
|
||||
// register source operands or one register source operand and one immediate
|
||||
// operand. The instruction takes one cycle to execute in each of the
|
||||
// pipeline stages except the execute stage, which takes two cycles. All of
|
||||
// the source operands are read during the decode stage and the result is
|
||||
// ready after the execute stage.
|
||||
InstrItinData< IIC_MEMl,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<2,[EX]>], // two cycles in execute stage
|
||||
[ 3 // result ready after four cycles
|
||||
, 1 // second operand read after one cycle
|
||||
, 1 ]> // third operand read after one cycle
|
||||
]>;
|
@ -1,267 +0,0 @@
|
||||
//===-- MBlazeSchedule5.td - MBlaze Scheduling Definitions -*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MBlaze instruction itineraries for the five stage pipeline.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def MBlazePipe5Itineraries : ProcessorItineraries<
|
||||
[IF,ID,EX,MA,WB], [], [
|
||||
|
||||
// ALU instruction with one destination register and either two register
|
||||
// source operands or one register source operand and one immediate operand.
|
||||
// The instruction takes one cycle to execute in each of the stages. The
|
||||
// two source operands are read during the decode stage and the result is
|
||||
// ready after the execute stage.
|
||||
InstrItinData< IIC_ALU,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 2 // result ready after two cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// ALU multiply instruction with one destination register and either two
|
||||
// register source operands or one register source operand and one immediate
|
||||
// operand. The instruction takes one cycle to execute in each of the
|
||||
// pipeline stages. The two source operands are read during the decode stage
|
||||
// and the result is ready after the execute stage.
|
||||
InstrItinData< IIC_ALUm,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 2 // result ready after two cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// ALU divide instruction with one destination register two register source
|
||||
// operands. The instruction takes one cycle to execute in each the pipeline
|
||||
// stages except the memory access stage, which takes 31 cycles. The two
|
||||
// source operands are read during the decode stage and the result is ready
|
||||
// after the memory access stage.
|
||||
InstrItinData< IIC_ALUd,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<31,[MA]> // 31 cycles in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 33 // result ready after 33 cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Shift instruction with one destination register and either two register
|
||||
// source operands or one register source operand and one immediate operand.
|
||||
// The instruction takes one cycle to execute in each of the pipeline stages.
|
||||
// The two source operands are read during the decode stage and the result is
|
||||
// ready after the memory access stage.
|
||||
InstrItinData< IIC_SHT,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 3 // result ready after three cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Branch instruction with one source operand register. The instruction takes
|
||||
// one cycle to execute in each of the pipeline stages. The source operand is
|
||||
// read during the decode stage.
|
||||
InstrItinData< IIC_BR,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Conditional branch instruction with two source operand registers. The
|
||||
// instruction takes one cycle to execute in each of the pipeline stages. The
|
||||
// two source operands are read during the decode stage.
|
||||
InstrItinData< IIC_BRc,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Branch and link instruction with one destination register and one source
|
||||
// operand register. The instruction takes one cycle to execute in each of
|
||||
// the pipeline stages. The source operand is read during the decode stage
|
||||
// and the destination register is ready after the writeback stage.
|
||||
InstrItinData< IIC_BRl,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 4 // result ready after four cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Cache control instruction with two source operand registers. The
|
||||
// instruction takes one cycle to execute in each of the pipeline stages
|
||||
// except the memory access stage, which takes two cycles. The source
|
||||
// operands are read during the decode stage.
|
||||
InstrItinData< IIC_WDC,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<2,[MA]> // two cycles in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Floating point instruction with one destination register and two source
|
||||
// operand registers. The instruction takes one cycle to execute in each of
|
||||
// the pipeline stages except the memory access stage, which takes two
|
||||
// cycles. The source operands are read during the decode stage and the
|
||||
// results are ready after the writeback stage.
|
||||
InstrItinData< IIC_FPU,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<2,[MA]> // two cycles in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 5 // result ready after five cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Floating point divide instruction with one destination register and two
|
||||
// source operand registers. The instruction takes one cycle to execute in
|
||||
// each of the pipeline stages except the memory access stage, which takes 26
|
||||
// cycles. The source operands are read during the decode stage and the
|
||||
// results are ready after the writeback stage.
|
||||
InstrItinData< IIC_FPUd,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<26,[MA]> // 26 cycles in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 29 // result ready after 29 cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Convert floating point to integer instruction with one destination
|
||||
// register and one source operand register. The instruction takes one cycle
|
||||
// to execute in each of the pipeline stages except the memory access stage,
|
||||
// which takes three cycles. The source operands are read during the decode
|
||||
// stage and the results are ready after the writeback stage.
|
||||
InstrItinData< IIC_FPUi,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<3,[MA]> // three cycles in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 6 // result ready after six cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Convert integer to floating point instruction with one destination
|
||||
// register and one source operand register. The instruction takes one cycle
|
||||
// to execute in each of the pipeline stages except the memory access stage,
|
||||
// which takes two cycles. The source operands are read during the decode
|
||||
// stage and the results are ready after the writeback stage.
|
||||
InstrItinData< IIC_FPUf,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<2,[MA]> // two cycles in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 5 // result ready after five cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Floating point square root instruction with one destination register and
|
||||
// one source operand register. The instruction takes one cycle to execute in
|
||||
// each of the pipeline stages except the memory access stage, which takes 25
|
||||
// cycles. The source operands are read during the decode stage and the
|
||||
// results are ready after the writeback stage.
|
||||
InstrItinData< IIC_FPUs,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<25,[MA]> // 25 cycles in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 28 // result ready after 28 cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// Floating point comparison instruction with one destination register and
|
||||
// two source operand registers. The instruction takes one cycle to execute
|
||||
// in each of the pipeline stages. The source operands are read during the
|
||||
// decode stage and the results are ready after the execute stage.
|
||||
InstrItinData< IIC_FPUc,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 2 // result ready after two cycles
|
||||
, 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// FSL get instruction with one register or immediate source operand and one
|
||||
// destination register. The instruction takes one cycle to execute in each
|
||||
// of the pipeline stages. The one source operand is read during the decode
|
||||
// stage and the result is ready after the execute stage.
|
||||
InstrItinData< IIC_FSLg,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 2 // result ready after two cycles
|
||||
, 1 ]>, // first operand read after one cycle
|
||||
|
||||
// FSL put instruction with either two register source operands or one
|
||||
// register source operand and one immediate operand. There is no result
|
||||
// produced by the instruction. The instruction takes one cycle to execute in
|
||||
// each of the pipeline stages. The two source operands are read during the
|
||||
// decode stage.
|
||||
InstrItinData< IIC_FSLp,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 1 // first operand read after one cycle
|
||||
, 1 ]>, // second operand read after one cycle
|
||||
|
||||
// Memory store instruction with either three register source operands or two
|
||||
// register source operands and one immediate operand. There is no result
|
||||
// produced by the instruction. The instruction takes one cycle to execute in
|
||||
// each of the pipeline stages. All of the source operands are read during
|
||||
// the decode stage.
|
||||
InstrItinData< IIC_MEMs,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 1 // first operand read after one cycle
|
||||
, 1 // second operand read after one cycle
|
||||
, 1 ]>, // third operand read after one cycle
|
||||
|
||||
// Memory load instruction with one destination register and either two
|
||||
// register source operands or one register source operand and one immediate
|
||||
// operand. The instruction takes one cycle to execute in each of the
|
||||
// pipeline stages. All of the source operands are read during the decode
|
||||
// stage and the result is ready after the writeback stage.
|
||||
InstrItinData< IIC_MEMl,
|
||||
[ InstrStage<1,[IF]> // one cycle in fetch stage
|
||||
, InstrStage<1,[ID]> // one cycle in decode stage
|
||||
, InstrStage<1,[EX]> // one cycle in execute stage
|
||||
, InstrStage<1,[MA]> // one cycle in memory access stage
|
||||
, InstrStage<1,[WB]>], // one cycle in write back stage
|
||||
[ 4 // result ready after four cycles
|
||||
, 1 // second operand read after one cycle
|
||||
, 1 ]> // third operand read after one cycle
|
||||
]>;
|
@ -1,23 +0,0 @@
|
||||
//===-- MBlazeSelectionDAGInfo.cpp - MBlaze 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 MBlazeSelectionDAGInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "mblaze-selectiondag-info"
|
||||
#include "MBlazeTargetMachine.h"
|
||||
using namespace llvm;
|
||||
|
||||
MBlazeSelectionDAGInfo::MBlazeSelectionDAGInfo(const MBlazeTargetMachine &TM)
|
||||
: TargetSelectionDAGInfo(TM) {
|
||||
}
|
||||
|
||||
MBlazeSelectionDAGInfo::~MBlazeSelectionDAGInfo() {
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
//===-- MBlazeSelectionDAGInfo.h - MBlaze 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 MBlaze subclass for TargetSelectionDAGInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZESELECTIONDAGINFO_H
|
||||
#define MBLAZESELECTIONDAGINFO_H
|
||||
|
||||
#include "llvm/Target/TargetSelectionDAGInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MBlazeTargetMachine;
|
||||
|
||||
class MBlazeSelectionDAGInfo : public TargetSelectionDAGInfo {
|
||||
public:
|
||||
explicit MBlazeSelectionDAGInfo(const MBlazeTargetMachine &TM);
|
||||
~MBlazeSelectionDAGInfo();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,56 +0,0 @@
|
||||
//===-- MBlazeSubtarget.cpp - MBlaze Subtarget Information ----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the MBlaze specific subclass of TargetSubtargetInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeSubtarget.h"
|
||||
#include "MBlaze.h"
|
||||
#include "MBlazeRegisterInfo.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
#define GET_SUBTARGETINFO_TARGET_DESC
|
||||
#define GET_SUBTARGETINFO_CTOR
|
||||
#include "MBlazeGenSubtargetInfo.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MBlazeSubtarget::MBlazeSubtarget(const std::string &TT,
|
||||
const std::string &CPU,
|
||||
const std::string &FS):
|
||||
MBlazeGenSubtargetInfo(TT, CPU, FS),
|
||||
HasBarrel(false), HasDiv(false), HasMul(false), HasPatCmp(false),
|
||||
HasFPU(false), HasMul64(false), HasSqrt(false)
|
||||
{
|
||||
// Parse features string.
|
||||
std::string CPUName = CPU;
|
||||
if (CPUName.empty())
|
||||
CPUName = "mblaze";
|
||||
ParseSubtargetFeatures(CPUName, FS);
|
||||
|
||||
// Only use instruction scheduling if the selected CPU has an instruction
|
||||
// itinerary (the default CPU is the only one that doesn't).
|
||||
HasItin = CPUName != "mblaze";
|
||||
DEBUG(dbgs() << "CPU " << CPUName << "(" << HasItin << ")\n");
|
||||
|
||||
// Initialize scheduling itinerary for the specified CPU.
|
||||
InstrItins = getInstrItineraryForCPU(CPUName);
|
||||
}
|
||||
|
||||
bool MBlazeSubtarget::
|
||||
enablePostRAScheduler(CodeGenOpt::Level OptLevel,
|
||||
TargetSubtargetInfo::AntiDepBreakMode& Mode,
|
||||
RegClassVector& CriticalPathRCs) const {
|
||||
Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL;
|
||||
CriticalPathRCs.clear();
|
||||
CriticalPathRCs.push_back(&MBlaze::GPRRegClass);
|
||||
return HasItin && OptLevel >= CodeGenOpt::Default;
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
//===-- MBlazeSubtarget.h - Define Subtarget for the MBlaze ----*- 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 MBlaze specific subclass of TargetSubtargetInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZESUBTARGET_H
|
||||
#define MBLAZESUBTARGET_H
|
||||
|
||||
#include "llvm/MC/MCInstrItineraries.h"
|
||||
#include "llvm/Target/TargetSubtargetInfo.h"
|
||||
#include <string>
|
||||
|
||||
#define GET_SUBTARGETINFO_HEADER
|
||||
#include "MBlazeGenSubtargetInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
|
||||
class MBlazeSubtarget : public MBlazeGenSubtargetInfo {
|
||||
|
||||
protected:
|
||||
bool HasBarrel;
|
||||
bool HasDiv;
|
||||
bool HasMul;
|
||||
bool HasPatCmp;
|
||||
bool HasFPU;
|
||||
bool HasMul64;
|
||||
bool HasSqrt;
|
||||
bool HasItin;
|
||||
|
||||
InstrItineraryData InstrItins;
|
||||
|
||||
public:
|
||||
|
||||
/// This constructor initializes the data members to match that
|
||||
/// of the specified triple.
|
||||
MBlazeSubtarget(const std::string &TT, const std::string &CPU,
|
||||
const std::string &FS);
|
||||
|
||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
|
||||
|
||||
/// Compute the number of maximum number of issues per cycle for the
|
||||
/// MBlaze scheduling itineraries.
|
||||
void computeIssueWidth();
|
||||
|
||||
/// enablePostRAScheduler - True at 'More' optimization.
|
||||
bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
|
||||
TargetSubtargetInfo::AntiDepBreakMode& Mode,
|
||||
RegClassVector& CriticalPathRCs) const;
|
||||
|
||||
/// getInstrItins - Return the instruction itineraies based on subtarget.
|
||||
const InstrItineraryData &getInstrItineraryData() const { return InstrItins; }
|
||||
|
||||
bool hasItin() const { return HasItin; }
|
||||
bool hasPCMP() const { return HasPatCmp; }
|
||||
bool hasFPU() const { return HasFPU; }
|
||||
bool hasSqrt() const { return HasSqrt; }
|
||||
bool hasMul() const { return HasMul; }
|
||||
bool hasMul64() const { return HasMul64; }
|
||||
bool hasDiv() const { return HasDiv; }
|
||||
bool hasBarrel() const { return HasBarrel; }
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -1,82 +0,0 @@
|
||||
//===-- MBlazeTargetMachine.cpp - Define TargetMachine for MBlaze ---------===//
|
||||
//
|
||||
// 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 MBlaze target spec.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeTargetMachine.h"
|
||||
#include "MBlaze.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
using namespace llvm;
|
||||
|
||||
extern "C" void LLVMInitializeMBlazeTarget() {
|
||||
// Register the target.
|
||||
RegisterTargetMachine<MBlazeTargetMachine> X(TheMBlazeTarget);
|
||||
}
|
||||
|
||||
// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
|
||||
// The stack is always 8 byte aligned
|
||||
// On function prologue, the stack is created by decrementing
|
||||
// its pointer. Once decremented, all references are done with positive
|
||||
// offset from the stack/frame pointer, using StackGrowsUp enables
|
||||
// an easier handling.
|
||||
MBlazeTargetMachine::
|
||||
MBlazeTargetMachine(const Target &T, StringRef TT,
|
||||
StringRef CPU, StringRef FS, const TargetOptions &Options,
|
||||
Reloc::Model RM, CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL)
|
||||
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
|
||||
Subtarget(TT, CPU, FS),
|
||||
DL("E-p:32:32:32-i8:8:8-i16:16:16"),
|
||||
InstrInfo(*this),
|
||||
FrameLowering(Subtarget),
|
||||
TLInfo(*this), TSInfo(*this),
|
||||
InstrItins(Subtarget.getInstrItineraryData()) {
|
||||
initAsmInfo();
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// MBlaze Code Generator Pass Configuration Options.
|
||||
class MBlazePassConfig : public TargetPassConfig {
|
||||
public:
|
||||
MBlazePassConfig(MBlazeTargetMachine *TM, PassManagerBase &PM)
|
||||
: TargetPassConfig(TM, PM) {}
|
||||
|
||||
MBlazeTargetMachine &getMBlazeTargetMachine() const {
|
||||
return getTM<MBlazeTargetMachine>();
|
||||
}
|
||||
|
||||
virtual bool addInstSelector();
|
||||
virtual bool addPreEmitPass();
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TargetPassConfig *MBlazeTargetMachine::createPassConfig(PassManagerBase &PM) {
|
||||
return new MBlazePassConfig(this, PM);
|
||||
}
|
||||
|
||||
// Install an instruction selector pass using
|
||||
// the ISelDag to gen MBlaze code.
|
||||
bool MBlazePassConfig::addInstSelector() {
|
||||
addPass(createMBlazeISelDag(getMBlazeTargetMachine()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implemented by targets that want to run passes immediately before
|
||||
// machine code is emitted. return true if -print-machineinstrs should
|
||||
// print out the code after the passes.
|
||||
bool MBlazePassConfig::addPreEmitPass() {
|
||||
addPass(createMBlazeDelaySlotFillerPass(getMBlazeTargetMachine()));
|
||||
return true;
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
//===-- MBlazeTargetMachine.h - Define TargetMachine for MBlaze -*- 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 MBlaze specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZE_TARGETMACHINE_H
|
||||
#define MBLAZE_TARGETMACHINE_H
|
||||
|
||||
#include "MBlazeFrameLowering.h"
|
||||
#include "MBlazeISelLowering.h"
|
||||
#include "MBlazeInstrInfo.h"
|
||||
#include "MBlazeIntrinsicInfo.h"
|
||||
#include "MBlazeSelectionDAGInfo.h"
|
||||
#include "MBlazeSubtarget.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
namespace llvm {
|
||||
class formatted_raw_ostream;
|
||||
|
||||
class MBlazeTargetMachine : public LLVMTargetMachine {
|
||||
MBlazeSubtarget Subtarget;
|
||||
const DataLayout DL; // Calculates type size & alignment
|
||||
MBlazeInstrInfo InstrInfo;
|
||||
MBlazeFrameLowering FrameLowering;
|
||||
MBlazeTargetLowering TLInfo;
|
||||
MBlazeSelectionDAGInfo TSInfo;
|
||||
MBlazeIntrinsicInfo IntrinsicInfo;
|
||||
InstrItineraryData InstrItins;
|
||||
|
||||
public:
|
||||
MBlazeTargetMachine(const Target &T, StringRef TT,
|
||||
StringRef CPU, StringRef FS,
|
||||
const TargetOptions &Options,
|
||||
Reloc::Model RM, CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL);
|
||||
|
||||
virtual const MBlazeInstrInfo *getInstrInfo() const
|
||||
{ return &InstrInfo; }
|
||||
|
||||
virtual const InstrItineraryData *getInstrItineraryData() const
|
||||
{ return &InstrItins; }
|
||||
|
||||
virtual const TargetFrameLowering *getFrameLowering() const
|
||||
{ return &FrameLowering; }
|
||||
|
||||
virtual const MBlazeSubtarget *getSubtargetImpl() const
|
||||
{ return &Subtarget; }
|
||||
|
||||
virtual const DataLayout *getDataLayout() const
|
||||
{ return &DL;}
|
||||
|
||||
virtual const MBlazeRegisterInfo *getRegisterInfo() const
|
||||
{ return &InstrInfo.getRegisterInfo(); }
|
||||
|
||||
virtual const MBlazeTargetLowering *getTargetLowering() const
|
||||
{ return &TLInfo; }
|
||||
|
||||
virtual const MBlazeSelectionDAGInfo* getSelectionDAGInfo() const
|
||||
{ return &TSInfo; }
|
||||
|
||||
const TargetIntrinsicInfo *getIntrinsicInfo() const
|
||||
{ return &IntrinsicInfo; }
|
||||
|
||||
// Pass Pipeline Configuration
|
||||
virtual TargetPassConfig *createPassConfig(PassManagerBase &PM);
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -1,90 +0,0 @@
|
||||
//===-- MBlazeTargetObjectFile.cpp - MBlaze object files ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeTargetObjectFile.h"
|
||||
#include "MBlazeSubtarget.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;
|
||||
|
||||
void MBlazeTargetObjectFile::
|
||||
Initialize(MCContext &Ctx, const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
|
||||
SmallDataSection =
|
||||
getContext().getELFSection(".sdata", ELF::SHT_PROGBITS,
|
||||
ELF::SHF_WRITE |ELF::SHF_ALLOC,
|
||||
SectionKind::getDataRel());
|
||||
|
||||
SmallBSSSection =
|
||||
getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
|
||||
ELF::SHF_WRITE |ELF::SHF_ALLOC,
|
||||
SectionKind::getBSS());
|
||||
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return Size > 0 && Size <= 8;
|
||||
}
|
||||
|
||||
bool MBlazeTargetObjectFile::
|
||||
IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const {
|
||||
if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
|
||||
return false;
|
||||
|
||||
return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM));
|
||||
}
|
||||
|
||||
/// IsGlobalInSmallSection - Return true if this global address should be
|
||||
/// placed into small data/bss section.
|
||||
bool MBlazeTargetObjectFile::
|
||||
IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM,
|
||||
SectionKind Kind) const {
|
||||
// Only global variables, not functions.
|
||||
const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV);
|
||||
if (!GVA)
|
||||
return false;
|
||||
|
||||
// We can only do this for datarel or BSS objects for now.
|
||||
if (!Kind.isBSS() && !Kind.isDataRel())
|
||||
return false;
|
||||
|
||||
// If this is a internal constant string, there is a special
|
||||
// section for it, but not in small data/bss.
|
||||
if (Kind.isMergeable1ByteCString())
|
||||
return false;
|
||||
|
||||
Type *Ty = GV->getType()->getElementType();
|
||||
return IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(Ty));
|
||||
}
|
||||
|
||||
const MCSection *MBlazeTargetObjectFile::
|
||||
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
Mangler *Mang, const TargetMachine &TM) const {
|
||||
// TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*"
|
||||
// sections?
|
||||
|
||||
// Handle Small Section classification here.
|
||||
if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind))
|
||||
return SmallBSSSection;
|
||||
if (Kind.isDataNoRel() && IsGlobalInSmallSection(GV, TM, Kind))
|
||||
return SmallDataSection;
|
||||
|
||||
// Otherwise, we work the same as ELF.
|
||||
return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM);
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
//===-- llvm/Target/MBlazeTargetObjectFile.h - MBlaze Obj. Info -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TARGET_MBLAZE_TARGETOBJECTFILE_H
|
||||
#define LLVM_TARGET_MBLAZE_TARGETOBJECTFILE_H
|
||||
|
||||
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MBlazeTargetObjectFile : public TargetLoweringObjectFileELF {
|
||||
const MCSection *SmallDataSection;
|
||||
const MCSection *SmallBSSSection;
|
||||
public:
|
||||
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM);
|
||||
|
||||
/// IsGlobalInSmallSection - 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;
|
||||
|
||||
const MCSection *SelectSectionForGlobal(const GlobalValue *GV,
|
||||
SectionKind Kind,
|
||||
Mangler *Mang,
|
||||
const TargetMachine &TM) const;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -1,9 +0,0 @@
|
||||
add_llvm_library(LLVMMBlazeDesc
|
||||
MBlazeAsmBackend.cpp
|
||||
MBlazeMCAsmInfo.cpp
|
||||
MBlazeMCCodeEmitter.cpp
|
||||
MBlazeMCTargetDesc.cpp
|
||||
MBlazeELFObjectWriter.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMMBlazeDesc MBlazeCommonTableGen)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/MBlaze/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 = MBlazeDesc
|
||||
parent = MBlaze
|
||||
required_libraries = MBlazeAsmPrinter MBlazeInfo MC Support
|
||||
add_to_library_groups = MBlaze
|
@ -1,171 +0,0 @@
|
||||
//===-- MBlazeAsmBackend.cpp - MBlaze Assembler Backend -------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/MBlazeMCTargetDesc.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCELFSymbolFlags.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
static unsigned getFixupKindSize(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("invalid fixup kind!");
|
||||
case FK_Data_1: return 1;
|
||||
case FK_PCRel_2:
|
||||
case FK_Data_2: return 2;
|
||||
case FK_PCRel_4:
|
||||
case FK_Data_4: return 4;
|
||||
case FK_Data_8: return 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class MBlazeAsmBackend : public MCAsmBackend {
|
||||
public:
|
||||
MBlazeAsmBackend(const Target &T)
|
||||
: MCAsmBackend() {
|
||||
}
|
||||
|
||||
unsigned getNumFixupKinds() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const;
|
||||
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup,
|
||||
uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const;
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const;
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const;
|
||||
|
||||
unsigned getPointerSize() const {
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
|
||||
static unsigned getRelaxedOpcode(unsigned Op) {
|
||||
switch (Op) {
|
||||
default: return Op;
|
||||
case MBlaze::ADDIK: return MBlaze::ADDIK32;
|
||||
case MBlaze::ORI: return MBlaze::ORI32;
|
||||
case MBlaze::BRLID: return MBlaze::BRLID32;
|
||||
}
|
||||
}
|
||||
|
||||
bool MBlazeAsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
|
||||
if (getRelaxedOpcode(Inst.getOpcode()) == Inst.getOpcode())
|
||||
return false;
|
||||
|
||||
bool hasExprOrImm = false;
|
||||
for (unsigned i = 0; i < Inst.getNumOperands(); ++i)
|
||||
hasExprOrImm |= Inst.getOperand(i).isExpr();
|
||||
|
||||
return hasExprOrImm;
|
||||
}
|
||||
|
||||
bool MBlazeAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
|
||||
uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const {
|
||||
// FIXME: Is this right? It's what the "generic" code was doing before,
|
||||
// but is X86 specific. Is it actually true for MBlaze also, or was it
|
||||
// just close enough to not be a big deal?
|
||||
//
|
||||
// Relax if the value is too big for a (signed) i8.
|
||||
return int64_t(Value) != int64_t(int8_t(Value));
|
||||
}
|
||||
|
||||
void MBlazeAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
|
||||
Res = Inst;
|
||||
Res.setOpcode(getRelaxedOpcode(Inst.getOpcode()));
|
||||
}
|
||||
|
||||
bool MBlazeAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
|
||||
if ((Count % 4) != 0)
|
||||
return false;
|
||||
|
||||
for (uint64_t i = 0; i < Count; i += 4)
|
||||
OW->Write32(0x00000000);
|
||||
|
||||
return true;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace {
|
||||
class ELFMBlazeAsmBackend : public MBlazeAsmBackend {
|
||||
public:
|
||||
uint8_t OSABI;
|
||||
ELFMBlazeAsmBackend(const Target &T, uint8_t _OSABI)
|
||||
: MBlazeAsmBackend(T), OSABI(_OSABI) { }
|
||||
|
||||
void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
|
||||
uint64_t Value) const;
|
||||
|
||||
MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
|
||||
return createMBlazeELFObjectWriter(OS, OSABI);
|
||||
}
|
||||
};
|
||||
|
||||
void ELFMBlazeAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
|
||||
unsigned DataSize, uint64_t Value) const {
|
||||
unsigned Size = getFixupKindSize(Fixup.getKind());
|
||||
|
||||
assert(Fixup.getOffset() + Size <= DataSize &&
|
||||
"Invalid fixup offset!");
|
||||
|
||||
char *data = Data + Fixup.getOffset();
|
||||
switch (Size) {
|
||||
default: llvm_unreachable("Cannot fixup unknown value.");
|
||||
case 1: llvm_unreachable("Cannot fixup 1 byte value.");
|
||||
case 8: llvm_unreachable("Cannot fixup 8 byte value.");
|
||||
|
||||
case 4:
|
||||
*(data+7) = uint8_t(Value);
|
||||
*(data+6) = uint8_t(Value >> 8);
|
||||
*(data+3) = uint8_t(Value >> 16);
|
||||
*(data+2) = uint8_t(Value >> 24);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*(data+3) = uint8_t(Value >> 0);
|
||||
*(data+2) = uint8_t(Value >> 8);
|
||||
}
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
MCAsmBackend *llvm::createMBlazeAsmBackend(const Target &T, StringRef TT,
|
||||
StringRef CPU) {
|
||||
Triple TheTriple(TT);
|
||||
|
||||
if (TheTriple.isOSDarwin())
|
||||
assert(0 && "Mac not supported on MBlaze");
|
||||
|
||||
if (TheTriple.isOSWindows())
|
||||
assert(0 && "Windows not supported on MBlaze");
|
||||
|
||||
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
|
||||
return new ELFMBlazeAsmBackend(T, OSABI);
|
||||
}
|
@ -1,237 +0,0 @@
|
||||
//===-- MBlazeBaseInfo.h - Top level definitions for MBlaze -- --*- 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 MBlaze target useful for the compiler back-end and the MC libraries.
|
||||
// As such, it deliberately does not include references to LLVM core
|
||||
// code gen types, passes, etc..
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBlazeBASEINFO_H
|
||||
#define MBlazeBASEINFO_H
|
||||
|
||||
#include "MBlazeMCTargetDesc.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// MBlazeII - This namespace holds all of the target specific flags that
|
||||
/// instruction info tracks.
|
||||
///
|
||||
namespace MBlazeII {
|
||||
enum {
|
||||
// PseudoFrm - This represents an instruction that is a pseudo instruction
|
||||
// or one that has not been implemented yet. It is illegal to code generate
|
||||
// it, but tolerated for intermediate implementation stages.
|
||||
FPseudo = 0,
|
||||
FRRR,
|
||||
FRRI,
|
||||
FCRR,
|
||||
FCRI,
|
||||
FRCR,
|
||||
FRCI,
|
||||
FCCR,
|
||||
FCCI,
|
||||
FRRCI,
|
||||
FRRC,
|
||||
FRCX,
|
||||
FRCS,
|
||||
FCRCS,
|
||||
FCRCX,
|
||||
FCX,
|
||||
FCR,
|
||||
FRIR,
|
||||
FRRRR,
|
||||
FRI,
|
||||
FC,
|
||||
FRR,
|
||||
FormMask = 63
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// MBlaze Specific MachineOperand flags.
|
||||
// MO_NO_FLAG,
|
||||
|
||||
/// MO_GOT - Represents the offset into the global offset table at which
|
||||
/// the address the relocation entry symbol resides during execution.
|
||||
// MO_GOT,
|
||||
|
||||
/// MO_GOT_CALL - Represents the offset into the global offset table at
|
||||
/// which the address of a call site relocation entry symbol resides
|
||||
/// during execution. This is different from the above since this flag
|
||||
/// can only be present in call instructions.
|
||||
// MO_GOT_CALL,
|
||||
|
||||
/// MO_GPREL - Represents the offset from the current gp value to be used
|
||||
/// for the relocatable object file being produced.
|
||||
// MO_GPREL,
|
||||
|
||||
/// MO_ABS_HILO - Represents the hi or low part of an absolute symbol
|
||||
/// address.
|
||||
// MO_ABS_HILO
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
static inline bool isMBlazeRegister(unsigned Reg) {
|
||||
return Reg <= 31;
|
||||
}
|
||||
|
||||
static inline bool isSpecialMBlazeRegister(unsigned Reg) {
|
||||
switch (Reg) {
|
||||
case 0x0000 : case 0x0001 : case 0x0003 : case 0x0005 :
|
||||
case 0x0007 : case 0x000B : case 0x000D : case 0x1000 :
|
||||
case 0x1001 : case 0x1002 : case 0x1003 : case 0x1004 :
|
||||
case 0x2000 : case 0x2001 : case 0x2002 : case 0x2003 :
|
||||
case 0x2004 : case 0x2005 : case 0x2006 : case 0x2007 :
|
||||
case 0x2008 : case 0x2009 : case 0x200A : case 0x200B :
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// getMBlazeRegisterNumbering - Given the enum value for some register, e.g.
|
||||
/// MBlaze::R0, return the number that it corresponds to (e.g. 0).
|
||||
static inline unsigned getMBlazeRegisterNumbering(unsigned RegEnum) {
|
||||
switch (RegEnum) {
|
||||
case MBlaze::R0 : return 0;
|
||||
case MBlaze::R1 : return 1;
|
||||
case MBlaze::R2 : return 2;
|
||||
case MBlaze::R3 : return 3;
|
||||
case MBlaze::R4 : return 4;
|
||||
case MBlaze::R5 : return 5;
|
||||
case MBlaze::R6 : return 6;
|
||||
case MBlaze::R7 : return 7;
|
||||
case MBlaze::R8 : return 8;
|
||||
case MBlaze::R9 : return 9;
|
||||
case MBlaze::R10 : return 10;
|
||||
case MBlaze::R11 : return 11;
|
||||
case MBlaze::R12 : return 12;
|
||||
case MBlaze::R13 : return 13;
|
||||
case MBlaze::R14 : return 14;
|
||||
case MBlaze::R15 : return 15;
|
||||
case MBlaze::R16 : return 16;
|
||||
case MBlaze::R17 : return 17;
|
||||
case MBlaze::R18 : return 18;
|
||||
case MBlaze::R19 : return 19;
|
||||
case MBlaze::R20 : return 20;
|
||||
case MBlaze::R21 : return 21;
|
||||
case MBlaze::R22 : return 22;
|
||||
case MBlaze::R23 : return 23;
|
||||
case MBlaze::R24 : return 24;
|
||||
case MBlaze::R25 : return 25;
|
||||
case MBlaze::R26 : return 26;
|
||||
case MBlaze::R27 : return 27;
|
||||
case MBlaze::R28 : return 28;
|
||||
case MBlaze::R29 : return 29;
|
||||
case MBlaze::R30 : return 30;
|
||||
case MBlaze::R31 : return 31;
|
||||
case MBlaze::RPC : return 0x0000;
|
||||
case MBlaze::RMSR : return 0x0001;
|
||||
case MBlaze::REAR : return 0x0003;
|
||||
case MBlaze::RESR : return 0x0005;
|
||||
case MBlaze::RFSR : return 0x0007;
|
||||
case MBlaze::RBTR : return 0x000B;
|
||||
case MBlaze::REDR : return 0x000D;
|
||||
case MBlaze::RPID : return 0x1000;
|
||||
case MBlaze::RZPR : return 0x1001;
|
||||
case MBlaze::RTLBX : return 0x1002;
|
||||
case MBlaze::RTLBLO : return 0x1003;
|
||||
case MBlaze::RTLBHI : return 0x1004;
|
||||
case MBlaze::RPVR0 : return 0x2000;
|
||||
case MBlaze::RPVR1 : return 0x2001;
|
||||
case MBlaze::RPVR2 : return 0x2002;
|
||||
case MBlaze::RPVR3 : return 0x2003;
|
||||
case MBlaze::RPVR4 : return 0x2004;
|
||||
case MBlaze::RPVR5 : return 0x2005;
|
||||
case MBlaze::RPVR6 : return 0x2006;
|
||||
case MBlaze::RPVR7 : return 0x2007;
|
||||
case MBlaze::RPVR8 : return 0x2008;
|
||||
case MBlaze::RPVR9 : return 0x2009;
|
||||
case MBlaze::RPVR10 : return 0x200A;
|
||||
case MBlaze::RPVR11 : return 0x200B;
|
||||
default: llvm_unreachable("Unknown register number!");
|
||||
}
|
||||
}
|
||||
|
||||
/// getRegisterFromNumbering - Given the enum value for some register, e.g.
|
||||
/// MBlaze::R0, return the number that it corresponds to (e.g. 0).
|
||||
static inline unsigned getMBlazeRegisterFromNumbering(unsigned Reg) {
|
||||
switch (Reg) {
|
||||
case 0 : return MBlaze::R0;
|
||||
case 1 : return MBlaze::R1;
|
||||
case 2 : return MBlaze::R2;
|
||||
case 3 : return MBlaze::R3;
|
||||
case 4 : return MBlaze::R4;
|
||||
case 5 : return MBlaze::R5;
|
||||
case 6 : return MBlaze::R6;
|
||||
case 7 : return MBlaze::R7;
|
||||
case 8 : return MBlaze::R8;
|
||||
case 9 : return MBlaze::R9;
|
||||
case 10 : return MBlaze::R10;
|
||||
case 11 : return MBlaze::R11;
|
||||
case 12 : return MBlaze::R12;
|
||||
case 13 : return MBlaze::R13;
|
||||
case 14 : return MBlaze::R14;
|
||||
case 15 : return MBlaze::R15;
|
||||
case 16 : return MBlaze::R16;
|
||||
case 17 : return MBlaze::R17;
|
||||
case 18 : return MBlaze::R18;
|
||||
case 19 : return MBlaze::R19;
|
||||
case 20 : return MBlaze::R20;
|
||||
case 21 : return MBlaze::R21;
|
||||
case 22 : return MBlaze::R22;
|
||||
case 23 : return MBlaze::R23;
|
||||
case 24 : return MBlaze::R24;
|
||||
case 25 : return MBlaze::R25;
|
||||
case 26 : return MBlaze::R26;
|
||||
case 27 : return MBlaze::R27;
|
||||
case 28 : return MBlaze::R28;
|
||||
case 29 : return MBlaze::R29;
|
||||
case 30 : return MBlaze::R30;
|
||||
case 31 : return MBlaze::R31;
|
||||
default: llvm_unreachable("Unknown register number!");
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned getSpecialMBlazeRegisterFromNumbering(unsigned Reg) {
|
||||
switch (Reg) {
|
||||
case 0x0000 : return MBlaze::RPC;
|
||||
case 0x0001 : return MBlaze::RMSR;
|
||||
case 0x0003 : return MBlaze::REAR;
|
||||
case 0x0005 : return MBlaze::RESR;
|
||||
case 0x0007 : return MBlaze::RFSR;
|
||||
case 0x000B : return MBlaze::RBTR;
|
||||
case 0x000D : return MBlaze::REDR;
|
||||
case 0x1000 : return MBlaze::RPID;
|
||||
case 0x1001 : return MBlaze::RZPR;
|
||||
case 0x1002 : return MBlaze::RTLBX;
|
||||
case 0x1003 : return MBlaze::RTLBLO;
|
||||
case 0x1004 : return MBlaze::RTLBHI;
|
||||
case 0x2000 : return MBlaze::RPVR0;
|
||||
case 0x2001 : return MBlaze::RPVR1;
|
||||
case 0x2002 : return MBlaze::RPVR2;
|
||||
case 0x2003 : return MBlaze::RPVR3;
|
||||
case 0x2004 : return MBlaze::RPVR4;
|
||||
case 0x2005 : return MBlaze::RPVR5;
|
||||
case 0x2006 : return MBlaze::RPVR6;
|
||||
case 0x2007 : return MBlaze::RPVR7;
|
||||
case 0x2008 : return MBlaze::RPVR8;
|
||||
case 0x2009 : return MBlaze::RPVR9;
|
||||
case 0x200A : return MBlaze::RPVR10;
|
||||
case 0x200B : return MBlaze::RPVR11;
|
||||
default: llvm_unreachable("Unknown register number!");
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llvm;
|
||||
|
||||
#endif
|
@ -1,77 +0,0 @@
|
||||
//===-- MBlazeELFObjectWriter.cpp - MBlaze 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/MBlazeMCTargetDesc.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class MBlazeELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
MBlazeELFObjectWriter(uint8_t OSABI);
|
||||
|
||||
virtual ~MBlazeELFObjectWriter();
|
||||
protected:
|
||||
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
|
||||
bool IsPCRel, bool IsRelocWithSymbol,
|
||||
int64_t Addend) const;
|
||||
};
|
||||
}
|
||||
|
||||
MBlazeELFObjectWriter::MBlazeELFObjectWriter(uint8_t OSABI)
|
||||
: MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_MBLAZE,
|
||||
/*HasRelocationAddend*/ false) {}
|
||||
|
||||
MBlazeELFObjectWriter::~MBlazeELFObjectWriter() {
|
||||
}
|
||||
|
||||
unsigned MBlazeELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel,
|
||||
bool IsRelocWithSymbol,
|
||||
int64_t Addend) const {
|
||||
// determine the type of the relocation
|
||||
unsigned Type;
|
||||
if (IsPCRel) {
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
default:
|
||||
llvm_unreachable("Unimplemented");
|
||||
case FK_PCRel_4:
|
||||
Type = ELF::R_MICROBLAZE_64_PCREL;
|
||||
break;
|
||||
case FK_PCRel_2:
|
||||
Type = ELF::R_MICROBLAZE_32_PCREL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
default: llvm_unreachable("invalid fixup kind!");
|
||||
case FK_Data_4:
|
||||
Type = ((IsRelocWithSymbol || Addend !=0)
|
||||
? ELF::R_MICROBLAZE_32
|
||||
: ELF::R_MICROBLAZE_64);
|
||||
break;
|
||||
case FK_Data_2:
|
||||
Type = ELF::R_MICROBLAZE_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MCObjectWriter *llvm::createMBlazeELFObjectWriter(raw_ostream &OS,
|
||||
uint8_t OSABI) {
|
||||
MCELFObjectTargetWriter *MOTW = new MBlazeELFObjectWriter(OSABI);
|
||||
return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/ false);
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
//===-- MBlazeMCAsmInfo.cpp - MBlaze 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 MBlazeMCAsmInfo properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeMCAsmInfo.h"
|
||||
using namespace llvm;
|
||||
|
||||
void MBlazeMCAsmInfo::anchor() { }
|
||||
|
||||
MBlazeMCAsmInfo::MBlazeMCAsmInfo() {
|
||||
IsLittleEndian = false;
|
||||
StackGrowsUp = false;
|
||||
SupportsDebugInformation = true;
|
||||
AlignmentIsInBytes = false;
|
||||
PrivateGlobalPrefix = "$";
|
||||
GPRel32Directive = "\t.gpword\t";
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
//===-- MBlazeMCAsmInfo.h - MBlaze 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 MBlazeMCAsmInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZETARGETASMINFO_H
|
||||
#define MBLAZETARGETASMINFO_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class Target;
|
||||
|
||||
class MBlazeMCAsmInfo : public MCAsmInfo {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit MBlazeMCAsmInfo();
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -1,222 +0,0 @@
|
||||
//===-- MBlazeMCCodeEmitter.cpp - Convert MBlaze 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 MBlazeMCCodeEmitter class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "mccodeemitter"
|
||||
#include "MCTargetDesc/MBlazeMCTargetDesc.h"
|
||||
#include "MCTargetDesc/MBlazeBaseInfo.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
|
||||
|
||||
namespace {
|
||||
class MBlazeMCCodeEmitter : public MCCodeEmitter {
|
||||
MBlazeMCCodeEmitter(const MBlazeMCCodeEmitter &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const MBlazeMCCodeEmitter &) LLVM_DELETED_FUNCTION;
|
||||
const MCInstrInfo &MCII;
|
||||
|
||||
public:
|
||||
MBlazeMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
|
||||
MCContext &ctx)
|
||||
: MCII(mcii) {
|
||||
}
|
||||
|
||||
~MBlazeMCCodeEmitter() {}
|
||||
|
||||
// getBinaryCodeForInstr - TableGen'erated function for getting the
|
||||
// binary encoding for an instruction.
|
||||
uint64_t getBinaryCodeForInstr(const MCInst &MI) const;
|
||||
|
||||
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
||||
/// operand requires relocation, record the relocation and return zero.
|
||||
unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO) const;
|
||||
unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) const {
|
||||
return getMachineOpValue(MI, MI.getOperand(OpIdx));
|
||||
}
|
||||
|
||||
static unsigned GetMBlazeRegNum(const MCOperand &MO) {
|
||||
// FIXME: getMBlazeRegisterNumbering() is sufficient?
|
||||
llvm_unreachable("MBlazeMCCodeEmitter::GetMBlazeRegNum() not yet "
|
||||
"implemented.");
|
||||
}
|
||||
|
||||
void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
|
||||
// The MicroBlaze uses a bit reversed format so we need to reverse the
|
||||
// order of the bits. Taken from:
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
C = ((C * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
|
||||
|
||||
OS << (char)C;
|
||||
++CurByte;
|
||||
}
|
||||
|
||||
void EmitRawByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
|
||||
OS << (char)C;
|
||||
++CurByte;
|
||||
}
|
||||
|
||||
void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte,
|
||||
raw_ostream &OS) const {
|
||||
assert(Size <= 8 && "size too big in emit constant");
|
||||
|
||||
for (unsigned i = 0; i != Size; ++i) {
|
||||
EmitByte(Val & 255, CurByte, OS);
|
||||
Val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const;
|
||||
void EmitIMM(const MCInst &MI, unsigned &CurByte, raw_ostream &OS) const;
|
||||
|
||||
void EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel,
|
||||
unsigned &CurByte, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
MCCodeEmitter *llvm::createMBlazeMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCSubtargetInfo &STI,
|
||||
MCContext &Ctx) {
|
||||
return new MBlazeMCCodeEmitter(MCII, STI, Ctx);
|
||||
}
|
||||
|
||||
/// getMachineOpValue - Return binary encoding of operand. If the machine
|
||||
/// operand requires relocation, record the relocation and return zero.
|
||||
unsigned MBlazeMCCodeEmitter::getMachineOpValue(const MCInst &MI,
|
||||
const MCOperand &MO) const {
|
||||
if (MO.isReg())
|
||||
return getMBlazeRegisterNumbering(MO.getReg());
|
||||
if (MO.isImm())
|
||||
return static_cast<unsigned>(MO.getImm());
|
||||
if (MO.isExpr())
|
||||
return 0; // The relocation has already been recorded at this point.
|
||||
#ifndef NDEBUG
|
||||
errs() << MO;
|
||||
#endif
|
||||
llvm_unreachable(0);
|
||||
}
|
||||
|
||||
void MBlazeMCCodeEmitter::
|
||||
EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const {
|
||||
int32_t val = (int32_t)imm.getImm();
|
||||
if (val > 32767 || val < -32768) {
|
||||
EmitByte(0x0D, CurByte, OS);
|
||||
EmitByte(0x00, CurByte, OS);
|
||||
EmitRawByte((val >> 24) & 0xFF, CurByte, OS);
|
||||
EmitRawByte((val >> 16) & 0xFF, CurByte, OS);
|
||||
}
|
||||
}
|
||||
|
||||
void MBlazeMCCodeEmitter::
|
||||
EmitIMM(const MCInst &MI, unsigned &CurByte,raw_ostream &OS) const {
|
||||
switch (MI.getOpcode()) {
|
||||
default: break;
|
||||
|
||||
case MBlaze::ADDIK32:
|
||||
case MBlaze::ORI32:
|
||||
case MBlaze::BRLID32:
|
||||
EmitByte(0x0D, CurByte, OS);
|
||||
EmitByte(0x00, CurByte, OS);
|
||||
EmitRawByte(0, CurByte, OS);
|
||||
EmitRawByte(0, CurByte, OS);
|
||||
}
|
||||
}
|
||||
|
||||
void MBlazeMCCodeEmitter::
|
||||
EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, unsigned &CurByte,
|
||||
raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
assert(MI.getNumOperands()>opNo && "Not enought operands for instruction");
|
||||
|
||||
MCOperand oper = MI.getOperand(opNo);
|
||||
|
||||
if (oper.isImm()) {
|
||||
EmitIMM(oper, CurByte, OS);
|
||||
} else if (oper.isExpr()) {
|
||||
MCFixupKind FixupKind;
|
||||
switch (MI.getOpcode()) {
|
||||
default:
|
||||
FixupKind = pcrel ? FK_PCRel_2 : FK_Data_2;
|
||||
Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
|
||||
break;
|
||||
case MBlaze::ORI32:
|
||||
case MBlaze::ADDIK32:
|
||||
case MBlaze::BRLID32:
|
||||
FixupKind = pcrel ? FK_PCRel_4 : FK_Data_4;
|
||||
Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MBlazeMCCodeEmitter::
|
||||
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
unsigned Opcode = MI.getOpcode();
|
||||
const MCInstrDesc &Desc = MCII.get(Opcode);
|
||||
uint64_t TSFlags = Desc.TSFlags;
|
||||
// Keep track of the current byte being emitted.
|
||||
unsigned CurByte = 0;
|
||||
|
||||
// Emit an IMM instruction if the instruction we are encoding requires it
|
||||
EmitIMM(MI,CurByte,OS);
|
||||
|
||||
switch ((TSFlags & MBlazeII::FormMask)) {
|
||||
default: break;
|
||||
case MBlazeII::FPseudo:
|
||||
// Pseudo instructions don't get encoded.
|
||||
return;
|
||||
case MBlazeII::FRRI:
|
||||
EmitImmediate(MI, 2, false, CurByte, OS, Fixups);
|
||||
break;
|
||||
case MBlazeII::FRIR:
|
||||
EmitImmediate(MI, 1, false, CurByte, OS, Fixups);
|
||||
break;
|
||||
case MBlazeII::FCRI:
|
||||
EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
|
||||
break;
|
||||
case MBlazeII::FRCI:
|
||||
EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
|
||||
case MBlazeII::FCCI:
|
||||
EmitImmediate(MI, 0, true, CurByte, OS, Fixups);
|
||||
break;
|
||||
}
|
||||
|
||||
++MCNumEmitted; // Keep track of the # of mi's emitted
|
||||
unsigned Value = getBinaryCodeForInstr(MI);
|
||||
EmitConstant(Value, 4, CurByte, OS);
|
||||
}
|
||||
|
||||
// FIXME: These #defines shouldn't be necessary. Instead, tblgen should
|
||||
// be able to generate code emitter helpers for either variant, like it
|
||||
// does for the AsmWriter.
|
||||
#define MBlazeCodeEmitter MBlazeMCCodeEmitter
|
||||
#define MachineInstr MCInst
|
||||
#include "MBlazeGenCodeEmitter.inc"
|
||||
#undef MBlazeCodeEmitter
|
||||
#undef MachineInstr
|
@ -1,137 +0,0 @@
|
||||
//===-- MBlazeMCTargetDesc.cpp - MBlaze 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 MBlaze specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlazeMCTargetDesc.h"
|
||||
#include "InstPrinter/MBlazeInstPrinter.h"
|
||||
#include "MBlazeMCAsmInfo.h"
|
||||
#include "llvm/MC/MCCodeGenInfo.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.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 "MBlazeGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_MC_DESC
|
||||
#include "MBlazeGenSubtargetInfo.inc"
|
||||
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#include "MBlazeGenRegisterInfo.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
||||
static MCInstrInfo *createMBlazeMCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitMBlazeMCInstrInfo(X);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createMBlazeMCRegisterInfo(StringRef TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitMBlazeMCRegisterInfo(X, MBlaze::R15);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCSubtargetInfo *createMBlazeMCSubtargetInfo(StringRef TT, StringRef CPU,
|
||||
StringRef FS) {
|
||||
MCSubtargetInfo *X = new MCSubtargetInfo();
|
||||
InitMBlazeMCSubtargetInfo(X, TT, CPU, FS);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) {
|
||||
return new MBlazeMCAsmInfo();
|
||||
}
|
||||
|
||||
static MCCodeGenInfo *createMBlazeMCCodeGenInfo(StringRef TT, Reloc::Model RM,
|
||||
CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL) {
|
||||
MCCodeGenInfo *X = new MCCodeGenInfo();
|
||||
if (RM == Reloc::Default)
|
||||
RM = Reloc::Static;
|
||||
if (CM == CodeModel::Default)
|
||||
CM = CodeModel::Small;
|
||||
X->InitMCCodeGenInfo(RM, CM, OL);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
|
||||
MCContext &Ctx, MCAsmBackend &MAB,
|
||||
raw_ostream &_OS,
|
||||
MCCodeEmitter *_Emitter,
|
||||
bool RelaxAll,
|
||||
bool NoExecStack) {
|
||||
Triple TheTriple(TT);
|
||||
|
||||
if (TheTriple.isOSDarwin()) {
|
||||
llvm_unreachable("MBlaze does not support Darwin MACH-O format");
|
||||
}
|
||||
|
||||
if (TheTriple.isOSWindows()) {
|
||||
llvm_unreachable("MBlaze does not support Windows COFF format");
|
||||
}
|
||||
|
||||
return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack);
|
||||
}
|
||||
|
||||
static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T,
|
||||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCSubtargetInfo &STI) {
|
||||
if (SyntaxVariant == 0)
|
||||
return new MBlazeInstPrinter(MAI, MII, MRI);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Force static initialization.
|
||||
extern "C" void LLVMInitializeMBlazeTargetMC() {
|
||||
// Register the MC asm info.
|
||||
RegisterMCAsmInfoFn X(TheMBlazeTarget, createMCAsmInfo);
|
||||
|
||||
// Register the MC codegen info.
|
||||
TargetRegistry::RegisterMCCodeGenInfo(TheMBlazeTarget,
|
||||
createMBlazeMCCodeGenInfo);
|
||||
|
||||
// Register the MC instruction info.
|
||||
TargetRegistry::RegisterMCInstrInfo(TheMBlazeTarget, createMBlazeMCInstrInfo);
|
||||
|
||||
// Register the MC register info.
|
||||
TargetRegistry::RegisterMCRegInfo(TheMBlazeTarget,
|
||||
createMBlazeMCRegisterInfo);
|
||||
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(TheMBlazeTarget,
|
||||
createMBlazeMCSubtargetInfo);
|
||||
|
||||
// Register the MC code emitter
|
||||
TargetRegistry::RegisterMCCodeEmitter(TheMBlazeTarget,
|
||||
llvm::createMBlazeMCCodeEmitter);
|
||||
|
||||
// Register the asm backend
|
||||
TargetRegistry::RegisterMCAsmBackend(TheMBlazeTarget,
|
||||
createMBlazeAsmBackend);
|
||||
|
||||
// Register the object streamer
|
||||
TargetRegistry::RegisterMCObjectStreamer(TheMBlazeTarget,
|
||||
createMCStreamer);
|
||||
|
||||
// Register the MCInstPrinter.
|
||||
TargetRegistry::RegisterMCInstPrinter(TheMBlazeTarget,
|
||||
createMBlazeMCInstPrinter);
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
//===-- MBlazeMCTargetDesc.h - MBlaze 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 MBlaze specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MBLAZEMCTARGETDESC_H
|
||||
#define MBLAZEMCTARGETDESC_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmBackend;
|
||||
class MCContext;
|
||||
class MCCodeEmitter;
|
||||
class MCInstrInfo;
|
||||
class MCObjectWriter;
|
||||
class MCRegisterInfo;
|
||||
class MCSubtargetInfo;
|
||||
class Target;
|
||||
class StringRef;
|
||||
class raw_ostream;
|
||||
|
||||
extern Target TheMBlazeTarget;
|
||||
|
||||
MCCodeEmitter *createMBlazeMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
const MCSubtargetInfo &STI,
|
||||
MCContext &Ctx);
|
||||
|
||||
MCAsmBackend *createMBlazeAsmBackend(const Target &T, StringRef TT,
|
||||
StringRef CPU);
|
||||
|
||||
MCObjectWriter *createMBlazeELFObjectWriter(raw_ostream &OS, uint8_t OSABI);
|
||||
} // End llvm namespace
|
||||
|
||||
// Defines symbolic names for MBlaze registers. This defines a mapping from
|
||||
// register name to register number.
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "MBlazeGenRegisterInfo.inc"
|
||||
|
||||
// Defines symbolic names for the MBlaze instructions.
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "MBlazeGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "MBlazeGenSubtargetInfo.inc"
|
||||
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
##===- lib/Target/MBlaze/TargetDesc/Makefile ---------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL = ../../../..
|
||||
LIBRARYNAME = LLVMMBlazeDesc
|
||||
|
||||
# Hack: we need to include 'main' target directory to grab private headers
|
||||
CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
@ -1,23 +0,0 @@
|
||||
##===- lib/Target/MBlaze/Makefile --------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../..
|
||||
LIBRARYNAME = LLVMMBlazeCodeGen
|
||||
TARGET = MBlaze
|
||||
|
||||
# Make sure that tblgen is run, first thing.
|
||||
BUILT_SOURCES = MBlazeGenRegisterInfo.inc MBlazeGenInstrInfo.inc \
|
||||
MBlazeGenAsmWriter.inc \
|
||||
MBlazeGenDAGISel.inc MBlazeGenAsmMatcher.inc \
|
||||
MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \
|
||||
MBlazeGenSubtargetInfo.inc MBlazeGenIntrinsics.inc
|
||||
|
||||
DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
@ -1,21 +0,0 @@
|
||||
* Writing out ELF files is close to working but the following needs to
|
||||
be examined more closely:
|
||||
- Relocations use 2-byte / 4-byte to terminology in reference to
|
||||
the size of the immediate value being changed. The Xilinx
|
||||
terminology seems to be (???) 4-byte / 8-byte in reference
|
||||
to the number of bytes of instructions that are being changed.
|
||||
|
||||
* Code generation seems to work relatively well now but the following
|
||||
needs to be examined more closely:
|
||||
- The stack layout needs to be examined to make sure it meets
|
||||
the standard, especially in regards to var arg functions.
|
||||
- Look at the MBlazeGenFastISel.inc stuff and make use of it
|
||||
if appropriate.
|
||||
|
||||
* A basic assembly parser is present now and seems to parse most things.
|
||||
There are a few things that need to be looked at:
|
||||
- There are some instructions that are not generated by the backend
|
||||
and have not been tested as far as the parser is concerned.
|
||||
- The assembly parser does not use many MicroBlaze specific directives.
|
||||
I should investigate if there are MicroBlaze specific directive and,
|
||||
if there are, add them.
|
@ -1,8 +0,0 @@
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.. )
|
||||
|
||||
add_llvm_library(LLVMMBlazeInfo
|
||||
MBlazeTargetInfo.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMMBlazeInfo MBlazeCommonTableGen)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/MBlaze/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 = MBlazeInfo
|
||||
parent = MBlaze
|
||||
required_libraries = MC Support Target
|
||||
add_to_library_groups = MBlaze
|
@ -1,19 +0,0 @@
|
||||
//===-- MBlazeTargetInfo.cpp - MBlaze Target Implementation ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MBlaze.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
using namespace llvm;
|
||||
|
||||
Target llvm::TheMBlazeTarget;
|
||||
|
||||
extern "C" void LLVMInitializeMBlazeTargetInfo() {
|
||||
RegisterTarget<Triple::mblaze> X(TheMBlazeTarget, "mblaze", "MBlaze");
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
##===- lib/Target/MBlaze/TargetInfo/Makefile ---------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../../..
|
||||
LIBRARYNAME = LLVMMBlazeInfo
|
||||
|
||||
# Hack: we need to include 'main' target directory to grab private headers
|
||||
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
@ -310,7 +310,6 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch],
|
||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
mblaze-*) llvm_cv_target_arch="MBlaze" ;;
|
||||
nvptx-*) llvm_cv_target_arch="NVPTX" ;;
|
||||
s390x-*) llvm_cv_target_arch="SystemZ" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
@ -481,7 +480,6 @@ else
|
||||
XCore) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;;
|
||||
*) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
@ -600,7 +598,7 @@ if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
fi
|
||||
case "$enableval" in
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend MBlaze NVPTX Hexagon SystemZ R600" ;;
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600" ;;
|
||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||
case "$a_target" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -617,7 +615,6 @@ case "$enableval" in
|
||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;;
|
||||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
|
||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="R600 $TARGETS_TO_BUILD" ;;
|
||||
@ -629,7 +626,6 @@ case "$enableval" in
|
||||
AArch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;;
|
||||
ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;;
|
||||
Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
|
9
projects/sample/configure
vendored
9
projects/sample/configure
vendored
@ -3850,7 +3850,6 @@ else
|
||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
mblaze-*) llvm_cv_target_arch="MBlaze" ;;
|
||||
nvptx-*) llvm_cv_target_arch="NVPTX" ;;
|
||||
s390x-*) llvm_cv_target_arch="SystemZ" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
@ -5112,8 +5111,6 @@ else
|
||||
MSP430) TARGET_HAS_JIT=0
|
||||
;;
|
||||
Hexagon) TARGET_HAS_JIT=0
|
||||
;;
|
||||
MBlaze) TARGET_HAS_JIT=0
|
||||
;;
|
||||
NVPTX) TARGET_HAS_JIT=0
|
||||
;;
|
||||
@ -5303,7 +5300,7 @@ if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
fi
|
||||
case "$enableval" in
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend MBlaze NVPTX Hexagon SystemZ R600" ;;
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC AArch64 ARM Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600" ;;
|
||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||
case "$a_target" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -5320,7 +5317,6 @@ case "$enableval" in
|
||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;;
|
||||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
|
||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="R600 $TARGETS_TO_BUILD" ;;
|
||||
@ -5332,7 +5328,6 @@ case "$enableval" in
|
||||
AArch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;;
|
||||
ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;;
|
||||
Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
@ -10344,7 +10339,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 10347 "configure"
|
||||
#line 10342 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
|
@ -1 +0,0 @@
|
||||
RUN: llc -O0 -march=mblaze -asm-verbose < %S/../Inputs/DbgValueOtherTargets.ll | FileCheck %S/../Inputs/DbgValueOtherTargets.ll
|
@ -1,72 +0,0 @@
|
||||
; Ensure that the select instruction is supported and is lowered to
|
||||
; some sort of branch instruction.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s
|
||||
|
||||
declare i32 @printf(i8*, ...)
|
||||
@MSG = internal constant [13 x i8] c"Message: %d\0A\00"
|
||||
|
||||
@BLKS = private constant [5 x i8*]
|
||||
[ i8* blockaddress(@brind, %L1),
|
||||
i8* blockaddress(@brind, %L2),
|
||||
i8* blockaddress(@brind, %L3),
|
||||
i8* blockaddress(@brind, %L4),
|
||||
i8* blockaddress(@brind, %L5) ]
|
||||
|
||||
define i32 @brind(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: brind:
|
||||
entry:
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
%tmp.0 = phi i32 [ 0, %entry ], [ %tmp.8, %finish ]
|
||||
%dst.0 = getelementptr [5 x i8*]* @BLKS, i32 0, i32 %tmp.0
|
||||
%dst.1 = load i8** %dst.0
|
||||
indirectbr i8* %dst.1, [ label %L1,
|
||||
label %L2,
|
||||
label %L3,
|
||||
label %L4,
|
||||
label %L5 ]
|
||||
; CHECK: brad {{r[0-9]*}}
|
||||
|
||||
L1:
|
||||
%tmp.1 = add i32 %a, %b
|
||||
br label %finish
|
||||
; CHECK: brid
|
||||
|
||||
L2:
|
||||
%tmp.2 = sub i32 %a, %b
|
||||
br label %finish
|
||||
; CHECK: brid
|
||||
|
||||
L3:
|
||||
%tmp.3 = mul i32 %a, %b
|
||||
br label %finish
|
||||
; CHECK: brid
|
||||
|
||||
L4:
|
||||
%tmp.4 = sdiv i32 %a, %b
|
||||
br label %finish
|
||||
; CHECK: brid
|
||||
|
||||
L5:
|
||||
%tmp.5 = srem i32 %a, %b
|
||||
br label %finish
|
||||
|
||||
finish:
|
||||
%tmp.6 = phi i32 [ %tmp.1, %L1 ],
|
||||
[ %tmp.2, %L2 ],
|
||||
[ %tmp.3, %L3 ],
|
||||
[ %tmp.4, %L4 ],
|
||||
[ %tmp.5, %L5 ]
|
||||
|
||||
call i32 (i8*,...)* @printf( i8* getelementptr([13 x i8]* @MSG,i32 0,i32 0),
|
||||
i32 %tmp.6)
|
||||
|
||||
%tmp.7 = add i32 %tmp.0, 1
|
||||
%tmp.8 = urem i32 %tmp.7, 5
|
||||
|
||||
br label %loop
|
||||
; CHECK: brad {{r[0-9]*}}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
; Ensure that indirect calls work and that they are lowered to some
|
||||
; sort of branch and link instruction.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s
|
||||
|
||||
declare i32 @printf(i8*, ...)
|
||||
@MSG = internal constant [13 x i8] c"Message: %d\0A\00"
|
||||
|
||||
@FUNS = private constant [5 x i32 (i32,i32)*]
|
||||
[ i32 (i32,i32)* @doadd,
|
||||
i32 (i32,i32)* @dosub,
|
||||
i32 (i32,i32)* @domul,
|
||||
i32 (i32,i32)* @dodiv,
|
||||
i32 (i32,i32)* @dorem ]
|
||||
|
||||
define i32 @doadd(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: doadd:
|
||||
%tmp.0 = add i32 %a, %b
|
||||
ret i32 %tmp.0
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i32 @dosub(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: dosub:
|
||||
%tmp.0 = sub i32 %a, %b
|
||||
ret i32 %tmp.0
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i32 @domul(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: domul:
|
||||
%tmp.0 = mul i32 %a, %b
|
||||
ret i32 %tmp.0
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i32 @dodiv(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: dodiv:
|
||||
%tmp.0 = sdiv i32 %a, %b
|
||||
ret i32 %tmp.0
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i32 @dorem(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: dorem:
|
||||
%tmp.0 = srem i32 %a, %b
|
||||
ret i32 %tmp.0
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i32 @callind(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: callind:
|
||||
entry:
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
%tmp.0 = phi i32 [ 0, %entry ], [ %tmp.3, %loop ]
|
||||
%dst.0 = getelementptr [5 x i32 (i32,i32)*]* @FUNS, i32 0, i32 %tmp.0
|
||||
%dst.1 = load i32 (i32,i32)** %dst.0
|
||||
%tmp.1 = call i32 %dst.1(i32 %a, i32 %b)
|
||||
; CHECK-NOT: brli
|
||||
; CHECK-NOT: brlai
|
||||
; CHECK: brl
|
||||
|
||||
call i32 (i8*,...)* @printf( i8* getelementptr([13 x i8]* @MSG,i32 0,i32 0),
|
||||
i32 %tmp.1)
|
||||
; CHECK: brl
|
||||
|
||||
%tmp.2 = add i32 %tmp.0, 1
|
||||
%tmp.3 = urem i32 %tmp.2, 5
|
||||
|
||||
br label %loop
|
||||
; CHECK: br
|
||||
}
|
@ -1,266 +0,0 @@
|
||||
; Test some of the calling convention lowering done by the MBlaze backend.
|
||||
; We test that integer values are passed in the correct registers and
|
||||
; returned in the correct registers. Additionally, we test that the stack
|
||||
; is used as appropriate for passing arguments that cannot be placed into
|
||||
; registers.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck %s
|
||||
|
||||
declare i32 @printf(i8*, ...)
|
||||
@MSG = internal constant [13 x i8] c"Message: %d\0A\00"
|
||||
|
||||
define void @params0_noret() {
|
||||
; CHECK-LABEL: params0_noret:
|
||||
ret void
|
||||
; CHECK-NOT: {{.* r3, .*, .*}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i8 @params0_8bitret() {
|
||||
; CHECK-LABEL: params0_8bitret:
|
||||
ret i8 1
|
||||
; CHECK-NOT: {{.* r3, .*, .*}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r0, 1}}
|
||||
}
|
||||
|
||||
define i16 @params0_16bitret() {
|
||||
; CHECK-LABEL: params0_16bitret:
|
||||
ret i16 1
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r0, 1}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
}
|
||||
|
||||
define i32 @params0_32bitret() {
|
||||
; CHECK-LABEL: params0_32bitret:
|
||||
ret i32 1
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r0, 1}}
|
||||
}
|
||||
|
||||
define i64 @params0_64bitret() {
|
||||
; CHECK-LABEL: params0_64bitret:
|
||||
ret i64 1
|
||||
; CHECK: {{.* r3, r0, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r4, r0, 1}}
|
||||
}
|
||||
|
||||
define i32 @params1_32bitret(i32 %a) {
|
||||
; CHECK-LABEL: params1_32bitret:
|
||||
ret i32 %a
|
||||
; CHECK-NOT: {{.* r3, .*, .*}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r5, r0}}
|
||||
}
|
||||
|
||||
define i32 @params2_32bitret(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: params2_32bitret:
|
||||
ret i32 %b
|
||||
; CHECK-NOT: {{.* r3, .*, .*}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r6, r0}}
|
||||
}
|
||||
|
||||
define i32 @params3_32bitret(i32 %a, i32 %b, i32 %c) {
|
||||
; CHECK-LABEL: params3_32bitret:
|
||||
ret i32 %c
|
||||
; CHECK-NOT: {{.* r3, .*, .*}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r7, r0}}
|
||||
}
|
||||
|
||||
define i32 @params4_32bitret(i32 %a, i32 %b, i32 %c, i32 %d) {
|
||||
; CHECK-LABEL: params4_32bitret:
|
||||
ret i32 %d
|
||||
; CHECK-NOT: {{.* r3, .*, .*}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r8, r0}}
|
||||
}
|
||||
|
||||
define i32 @params5_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
|
||||
; CHECK-LABEL: params5_32bitret:
|
||||
ret i32 %e
|
||||
; CHECK-NOT: {{.* r3, .*, .*}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r9, r0}}
|
||||
}
|
||||
|
||||
define i32 @params6_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
|
||||
; CHECK-LABEL: params6_32bitret:
|
||||
ret i32 %f
|
||||
; CHECK-NOT: {{.* r3, .*, .*}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
; CHECK: {{.* r3, r10, r0}}
|
||||
}
|
||||
|
||||
define i32 @params7_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
|
||||
i32 %g) {
|
||||
; CHECK-LABEL: params7_32bitret:
|
||||
ret i32 %g
|
||||
; CHECK: {{lwi? r3, r1, 32}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i32 @params8_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
|
||||
i32 %g, i32 %h) {
|
||||
; CHECK-LABEL: params8_32bitret:
|
||||
ret i32 %h
|
||||
; CHECK: {{lwi? r3, r1, 36}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i32 @params9_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
|
||||
i32 %g, i32 %h, i32 %i) {
|
||||
; CHECK-LABEL: params9_32bitret:
|
||||
ret i32 %i
|
||||
; CHECK: {{lwi? r3, r1, 40}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define i32 @params10_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
|
||||
i32 %g, i32 %h, i32 %i, i32 %j) {
|
||||
; CHECK-LABEL: params10_32bitret:
|
||||
ret i32 %j
|
||||
; CHECK: {{lwi? r3, r1, 44}}
|
||||
; CHECK-NOT: {{.* r4, .*, .*}}
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define void @testing() {
|
||||
%MSG.1 = getelementptr [13 x i8]* @MSG, i32 0, i32 0
|
||||
|
||||
call void @params0_noret()
|
||||
; CHECK: brlid
|
||||
|
||||
%tmp.1 = call i8 @params0_8bitret()
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i8 %tmp.1)
|
||||
|
||||
%tmp.2 = call i16 @params0_16bitret()
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i16 %tmp.2)
|
||||
|
||||
%tmp.3 = call i32 @params0_32bitret()
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.3)
|
||||
|
||||
%tmp.4 = call i64 @params0_64bitret()
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i64 %tmp.4)
|
||||
|
||||
%tmp.5 = call i32 @params1_32bitret(i32 1)
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.5)
|
||||
|
||||
%tmp.6 = call i32 @params2_32bitret(i32 1, i32 2)
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.6)
|
||||
|
||||
%tmp.7 = call i32 @params3_32bitret(i32 1, i32 2, i32 3)
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: {{.* r7, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.7)
|
||||
|
||||
%tmp.8 = call i32 @params4_32bitret(i32 1, i32 2, i32 3, i32 4)
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: {{.* r7, .*, .*}}
|
||||
; CHECK: {{.* r8, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.8)
|
||||
|
||||
%tmp.9 = call i32 @params5_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5)
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: {{.* r7, .*, .*}}
|
||||
; CHECK: {{.* r8, .*, .*}}
|
||||
; CHECK: {{.* r9, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.9)
|
||||
|
||||
%tmp.10 = call i32 @params6_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
|
||||
i32 6)
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: {{.* r7, .*, .*}}
|
||||
; CHECK: {{.* r8, .*, .*}}
|
||||
; CHECK: {{.* r9, .*, .*}}
|
||||
; CHECK: {{.* r10, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.10)
|
||||
|
||||
%tmp.11 = call i32 @params7_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
|
||||
i32 6, i32 7)
|
||||
; CHECK: {{swi? .*, r1, 28}}
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: {{.* r7, .*, .*}}
|
||||
; CHECK: {{.* r8, .*, .*}}
|
||||
; CHECK: {{.* r9, .*, .*}}
|
||||
; CHECK: {{.* r10, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.11)
|
||||
|
||||
%tmp.12 = call i32 @params8_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
|
||||
i32 6, i32 7, i32 8)
|
||||
; CHECK: {{swi? .*, r1, 32}}
|
||||
; CHECK: {{swi? .*, r1, 28}}
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: {{.* r7, .*, .*}}
|
||||
; CHECK: {{.* r8, .*, .*}}
|
||||
; CHECK: {{.* r9, .*, .*}}
|
||||
; CHECK: {{.* r10, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.12)
|
||||
|
||||
%tmp.13 = call i32 @params9_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
|
||||
i32 6, i32 7, i32 8, i32 9)
|
||||
; CHECK: {{swi? .*, r1, 36}}
|
||||
; CHECK: {{swi? .*, r1, 32}}
|
||||
; CHECK: {{swi? .*, r1, 28}}
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: {{.* r7, .*, .*}}
|
||||
; CHECK: {{.* r8, .*, .*}}
|
||||
; CHECK: {{.* r9, .*, .*}}
|
||||
; CHECK: {{.* r10, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.13)
|
||||
|
||||
%tmp.14 = call i32 @params10_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5,
|
||||
i32 6, i32 7, i32 8, i32 9, i32 10)
|
||||
; CHECK: {{swi? .*, r1, 40}}
|
||||
; CHECK: {{swi? .*, r1, 36}}
|
||||
; CHECK: {{swi? .*, r1, 32}}
|
||||
; CHECK: {{swi? .*, r1, 28}}
|
||||
; CHECK: {{.* r5, .*, .*}}
|
||||
; CHECK: {{.* r6, .*, .*}}
|
||||
; CHECK: {{.* r7, .*, .*}}
|
||||
; CHECK: {{.* r8, .*, .*}}
|
||||
; CHECK: {{.* r9, .*, .*}}
|
||||
; CHECK: {{.* r10, .*, .*}}
|
||||
; CHECK: brlid
|
||||
call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.14)
|
||||
|
||||
ret void
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
; Ensure that multiplication is lowered to function calls when the multiplier
|
||||
; unit is not available in the hardware and that function calls are not used
|
||||
; when the multiplier unit is available in the hardware.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
|
||||
; RUN: llc < %s -march=mblaze -mattr=+div | FileCheck -check-prefix=DIV %s
|
||||
|
||||
define i8 @test_i8(i8 %a, i8 %b) {
|
||||
; FUN-LABEL: test_i8:
|
||||
; DIV-LABEL: test_i8:
|
||||
|
||||
%tmp.1 = udiv i8 %a, %b
|
||||
; FUN-NOT: idiv
|
||||
; FUN: brlid
|
||||
; DIV-NOT: brlid
|
||||
; DIV: idiv
|
||||
|
||||
%tmp.2 = sdiv i8 %a, %b
|
||||
; FUN-NOT: idiv
|
||||
; FUN: brlid
|
||||
; DIV-NOT: brlid
|
||||
; DIV-NOT: idiv
|
||||
; DIV: idivu
|
||||
|
||||
%tmp.3 = add i8 %tmp.1, %tmp.2
|
||||
ret i8 %tmp.3
|
||||
; FUN: rtsd
|
||||
; DIV: rtsd
|
||||
}
|
||||
|
||||
define i16 @test_i16(i16 %a, i16 %b) {
|
||||
; FUN-LABEL: test_i16:
|
||||
; DIV-LABEL: test_i16:
|
||||
|
||||
%tmp.1 = udiv i16 %a, %b
|
||||
; FUN-NOT: idiv
|
||||
; FUN: brlid
|
||||
; DIV-NOT: brlid
|
||||
; DIV: idiv
|
||||
|
||||
%tmp.2 = sdiv i16 %a, %b
|
||||
; FUN-NOT: idiv
|
||||
; FUN: brlid
|
||||
; DIV-NOT: brlid
|
||||
; DIV-NOT: idiv
|
||||
; DIV: idivu
|
||||
|
||||
%tmp.3 = add i16 %tmp.1, %tmp.2
|
||||
ret i16 %tmp.3
|
||||
; FUN: rtsd
|
||||
; DIV: rtsd
|
||||
}
|
||||
|
||||
define i32 @test_i32(i32 %a, i32 %b) {
|
||||
; FUN-LABEL: test_i32:
|
||||
; DIV-LABEL: test_i32:
|
||||
|
||||
%tmp.1 = udiv i32 %a, %b
|
||||
; FUN-NOT: idiv
|
||||
; FUN: brlid
|
||||
; DIV-NOT: brlid
|
||||
; DIV: idiv
|
||||
|
||||
%tmp.2 = sdiv i32 %a, %b
|
||||
; FUN-NOT: idiv
|
||||
; FUN: brlid
|
||||
; DIV-NOT: brlid
|
||||
; DIV-NOT: idiv
|
||||
; DIV: idivu
|
||||
|
||||
%tmp.3 = add i32 %tmp.1, %tmp.2
|
||||
ret i32 %tmp.3
|
||||
; FUN: rtsd
|
||||
; DIV: rtsd
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
; Ensure that floating point operations are lowered to function calls when the
|
||||
; FPU is not available in the hardware and that function calls are not used
|
||||
; when the FPU is available in the hardware.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
|
||||
; RUN: llc < %s -march=mblaze -mattr=+fpu | FileCheck -check-prefix=FPU %s
|
||||
|
||||
define float @test_add(float %a, float %b) {
|
||||
; FUN-LABEL: test_add:
|
||||
; FPU-LABEL: test_add:
|
||||
|
||||
%tmp.1 = fadd float %a, %b
|
||||
; FUN: brlid
|
||||
; FPU-NOT: brlid
|
||||
|
||||
ret float %tmp.1
|
||||
; FUN: rtsd
|
||||
; FPU: rtsd
|
||||
; FUN-NOT: fadd
|
||||
; FPU-NEXT: fadd
|
||||
}
|
||||
|
||||
define float @test_sub(float %a, float %b) {
|
||||
; FUN-LABEL: test_sub:
|
||||
; FPU-LABEL: test_sub:
|
||||
|
||||
%tmp.1 = fsub float %a, %b
|
||||
; FUN: brlid
|
||||
; FPU-NOT: brlid
|
||||
|
||||
ret float %tmp.1
|
||||
; FUN: rtsd
|
||||
; FPU: rtsd
|
||||
; FUN-NOT: frsub
|
||||
; FPU-NEXT: frsub
|
||||
}
|
||||
|
||||
define float @test_mul(float %a, float %b) {
|
||||
; FUN-LABEL: test_mul:
|
||||
; FPU-LABEL: test_mul:
|
||||
|
||||
%tmp.1 = fmul float %a, %b
|
||||
; FUN: brlid
|
||||
; FPU-NOT: brlid
|
||||
|
||||
ret float %tmp.1
|
||||
; FUN: rtsd
|
||||
; FPU: rtsd
|
||||
; FUN-NOT: fmul
|
||||
; FPU-NEXT: fmul
|
||||
}
|
||||
|
||||
define float @test_div(float %a, float %b) {
|
||||
; FUN-LABEL: test_div:
|
||||
; FPU-LABEL: test_div:
|
||||
|
||||
%tmp.1 = fdiv float %a, %b
|
||||
; FUN: brlid
|
||||
; FPU-NOT: brlid
|
||||
|
||||
ret float %tmp.1
|
||||
; FUN: rtsd
|
||||
; FPU: rtsd
|
||||
; FUN-NOT: fdiv
|
||||
; FPU-NEXT: fdiv
|
||||
}
|
@ -1,319 +0,0 @@
|
||||
; Ensure that the FSL instrinsic instruction generate single FSL instructions
|
||||
; at the machine level. Additionally, ensure that dynamic values use the
|
||||
; dynamic version of the instructions and that constant values use the
|
||||
; constant version of the instructions.
|
||||
;
|
||||
; RUN: llc -O3 < %s -march=mblaze | FileCheck %s
|
||||
|
||||
declare i32 @llvm.mblaze.fsl.get(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.aget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.cget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.caget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.eget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.eaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.ecget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.ecaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.nget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.naget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.ncget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.ncaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.neget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.neaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.necget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.necaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.taget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tcget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tcaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.teget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.teaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tecget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tecaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tnget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tnaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tncget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tncaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tneget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tneaget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tnecget(i32 %port)
|
||||
declare i32 @llvm.mblaze.fsl.tnecaget(i32 %port)
|
||||
|
||||
declare void @llvm.mblaze.fsl.put(i32 %value, i32 %port)
|
||||
declare void @llvm.mblaze.fsl.aput(i32 %value, i32 %port)
|
||||
declare void @llvm.mblaze.fsl.cput(i32 %value, i32 %port)
|
||||
declare void @llvm.mblaze.fsl.caput(i32 %value, i32 %port)
|
||||
declare void @llvm.mblaze.fsl.nput(i32 %value, i32 %port)
|
||||
declare void @llvm.mblaze.fsl.naput(i32 %value, i32 %port)
|
||||
declare void @llvm.mblaze.fsl.ncput(i32 %value, i32 %port)
|
||||
declare void @llvm.mblaze.fsl.ncaput(i32 %value, i32 %port)
|
||||
declare void @llvm.mblaze.fsl.tput(i32 %port)
|
||||
declare void @llvm.mblaze.fsl.taput(i32 %port)
|
||||
declare void @llvm.mblaze.fsl.tcput(i32 %port)
|
||||
declare void @llvm.mblaze.fsl.tcaput(i32 %port)
|
||||
declare void @llvm.mblaze.fsl.tnput(i32 %port)
|
||||
declare void @llvm.mblaze.fsl.tnaput(i32 %port)
|
||||
declare void @llvm.mblaze.fsl.tncput(i32 %port)
|
||||
declare void @llvm.mblaze.fsl.tncaput(i32 %port)
|
||||
|
||||
define void @fsl_get(i32 %port) {
|
||||
; CHECK-LABEL: fsl_get:
|
||||
%v0 = call i32 @llvm.mblaze.fsl.get(i32 %port)
|
||||
; CHECK: getd
|
||||
%v1 = call i32 @llvm.mblaze.fsl.aget(i32 %port)
|
||||
; CHECK-NEXT: agetd
|
||||
%v2 = call i32 @llvm.mblaze.fsl.cget(i32 %port)
|
||||
; CHECK-NEXT: cgetd
|
||||
%v3 = call i32 @llvm.mblaze.fsl.caget(i32 %port)
|
||||
; CHECK-NEXT: cagetd
|
||||
%v4 = call i32 @llvm.mblaze.fsl.eget(i32 %port)
|
||||
; CHECK-NEXT: egetd
|
||||
%v5 = call i32 @llvm.mblaze.fsl.eaget(i32 %port)
|
||||
; CHECK-NEXT: eagetd
|
||||
%v6 = call i32 @llvm.mblaze.fsl.ecget(i32 %port)
|
||||
; CHECK-NEXT: ecgetd
|
||||
%v7 = call i32 @llvm.mblaze.fsl.ecaget(i32 %port)
|
||||
; CHECK-NEXT: ecagetd
|
||||
%v8 = call i32 @llvm.mblaze.fsl.nget(i32 %port)
|
||||
; CHECK-NEXT: ngetd
|
||||
%v9 = call i32 @llvm.mblaze.fsl.naget(i32 %port)
|
||||
; CHECK-NEXT: nagetd
|
||||
%v10 = call i32 @llvm.mblaze.fsl.ncget(i32 %port)
|
||||
; CHECK-NEXT: ncgetd
|
||||
%v11 = call i32 @llvm.mblaze.fsl.ncaget(i32 %port)
|
||||
; CHECK-NEXT: ncagetd
|
||||
%v12 = call i32 @llvm.mblaze.fsl.neget(i32 %port)
|
||||
; CHECK-NEXT: negetd
|
||||
%v13 = call i32 @llvm.mblaze.fsl.neaget(i32 %port)
|
||||
; CHECK-NEXT: neagetd
|
||||
%v14 = call i32 @llvm.mblaze.fsl.necget(i32 %port)
|
||||
; CHECK-NEXT: necgetd
|
||||
%v15 = call i32 @llvm.mblaze.fsl.necaget(i32 %port)
|
||||
; CHECK-NEXT: necagetd
|
||||
%v16 = call i32 @llvm.mblaze.fsl.tget(i32 %port)
|
||||
; CHECK-NEXT: tgetd
|
||||
%v17 = call i32 @llvm.mblaze.fsl.taget(i32 %port)
|
||||
; CHECK-NEXT: tagetd
|
||||
%v18 = call i32 @llvm.mblaze.fsl.tcget(i32 %port)
|
||||
; CHECK-NEXT: tcgetd
|
||||
%v19 = call i32 @llvm.mblaze.fsl.tcaget(i32 %port)
|
||||
; CHECK-NEXT: tcagetd
|
||||
%v20 = call i32 @llvm.mblaze.fsl.teget(i32 %port)
|
||||
; CHECK-NEXT: tegetd
|
||||
%v21 = call i32 @llvm.mblaze.fsl.teaget(i32 %port)
|
||||
; CHECK-NEXT: teagetd
|
||||
%v22 = call i32 @llvm.mblaze.fsl.tecget(i32 %port)
|
||||
; CHECK-NEXT: tecgetd
|
||||
%v23 = call i32 @llvm.mblaze.fsl.tecaget(i32 %port)
|
||||
; CHECK-NEXT: tecagetd
|
||||
%v24 = call i32 @llvm.mblaze.fsl.tnget(i32 %port)
|
||||
; CHECK-NEXT: tngetd
|
||||
%v25 = call i32 @llvm.mblaze.fsl.tnaget(i32 %port)
|
||||
; CHECK-NEXT: tnagetd
|
||||
%v26 = call i32 @llvm.mblaze.fsl.tncget(i32 %port)
|
||||
; CHECK-NEXT: tncgetd
|
||||
%v27 = call i32 @llvm.mblaze.fsl.tncaget(i32 %port)
|
||||
; CHECK-NEXT: tncagetd
|
||||
%v28 = call i32 @llvm.mblaze.fsl.tneget(i32 %port)
|
||||
; CHECK-NEXT: tnegetd
|
||||
%v29 = call i32 @llvm.mblaze.fsl.tneaget(i32 %port)
|
||||
; CHECK-NEXT: tneagetd
|
||||
%v30 = call i32 @llvm.mblaze.fsl.tnecget(i32 %port)
|
||||
; CHECK-NEXT: tnecgetd
|
||||
%v31 = call i32 @llvm.mblaze.fsl.tnecaget(i32 %port)
|
||||
; CHECK-NEXT: tnecagetd
|
||||
ret void
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define void @fslc_get() {
|
||||
; CHECK-LABEL: fslc_get:
|
||||
%v0 = call i32 @llvm.mblaze.fsl.get(i32 1)
|
||||
; CHECK: get
|
||||
%v1 = call i32 @llvm.mblaze.fsl.aget(i32 1)
|
||||
; CHECK-NOT: agetd
|
||||
; CHECK: aget
|
||||
%v2 = call i32 @llvm.mblaze.fsl.cget(i32 1)
|
||||
; CHECK-NOT: cgetd
|
||||
; CHECK: cget
|
||||
%v3 = call i32 @llvm.mblaze.fsl.caget(i32 1)
|
||||
; CHECK-NOT: cagetd
|
||||
; CHECK: caget
|
||||
%v4 = call i32 @llvm.mblaze.fsl.eget(i32 1)
|
||||
; CHECK-NOT: egetd
|
||||
; CHECK: eget
|
||||
%v5 = call i32 @llvm.mblaze.fsl.eaget(i32 1)
|
||||
; CHECK-NOT: eagetd
|
||||
; CHECK: eaget
|
||||
%v6 = call i32 @llvm.mblaze.fsl.ecget(i32 1)
|
||||
; CHECK-NOT: ecgetd
|
||||
; CHECK: ecget
|
||||
%v7 = call i32 @llvm.mblaze.fsl.ecaget(i32 1)
|
||||
; CHECK-NOT: ecagetd
|
||||
; CHECK: ecaget
|
||||
%v8 = call i32 @llvm.mblaze.fsl.nget(i32 1)
|
||||
; CHECK-NOT: ngetd
|
||||
; CHECK: nget
|
||||
%v9 = call i32 @llvm.mblaze.fsl.naget(i32 1)
|
||||
; CHECK-NOT: nagetd
|
||||
; CHECK: naget
|
||||
%v10 = call i32 @llvm.mblaze.fsl.ncget(i32 1)
|
||||
; CHECK-NOT: ncgetd
|
||||
; CHECK: ncget
|
||||
%v11 = call i32 @llvm.mblaze.fsl.ncaget(i32 1)
|
||||
; CHECK-NOT: ncagetd
|
||||
; CHECK: ncaget
|
||||
%v12 = call i32 @llvm.mblaze.fsl.neget(i32 1)
|
||||
; CHECK-NOT: negetd
|
||||
; CHECK: neget
|
||||
%v13 = call i32 @llvm.mblaze.fsl.neaget(i32 1)
|
||||
; CHECK-NOT: neagetd
|
||||
; CHECK: neaget
|
||||
%v14 = call i32 @llvm.mblaze.fsl.necget(i32 1)
|
||||
; CHECK-NOT: necgetd
|
||||
; CHECK: necget
|
||||
%v15 = call i32 @llvm.mblaze.fsl.necaget(i32 1)
|
||||
; CHECK-NOT: necagetd
|
||||
; CHECK: necaget
|
||||
%v16 = call i32 @llvm.mblaze.fsl.tget(i32 1)
|
||||
; CHECK-NOT: tgetd
|
||||
; CHECK: tget
|
||||
%v17 = call i32 @llvm.mblaze.fsl.taget(i32 1)
|
||||
; CHECK-NOT: tagetd
|
||||
; CHECK: taget
|
||||
%v18 = call i32 @llvm.mblaze.fsl.tcget(i32 1)
|
||||
; CHECK-NOT: tcgetd
|
||||
; CHECK: tcget
|
||||
%v19 = call i32 @llvm.mblaze.fsl.tcaget(i32 1)
|
||||
; CHECK-NOT: tcagetd
|
||||
; CHECK: tcaget
|
||||
%v20 = call i32 @llvm.mblaze.fsl.teget(i32 1)
|
||||
; CHECK-NOT: tegetd
|
||||
; CHECK: teget
|
||||
%v21 = call i32 @llvm.mblaze.fsl.teaget(i32 1)
|
||||
; CHECK-NOT: teagetd
|
||||
; CHECK: teaget
|
||||
%v22 = call i32 @llvm.mblaze.fsl.tecget(i32 1)
|
||||
; CHECK-NOT: tecgetd
|
||||
; CHECK: tecget
|
||||
%v23 = call i32 @llvm.mblaze.fsl.tecaget(i32 1)
|
||||
; CHECK-NOT: tecagetd
|
||||
; CHECK: tecaget
|
||||
%v24 = call i32 @llvm.mblaze.fsl.tnget(i32 1)
|
||||
; CHECK-NOT: tngetd
|
||||
; CHECK: tnget
|
||||
%v25 = call i32 @llvm.mblaze.fsl.tnaget(i32 1)
|
||||
; CHECK-NOT: tnagetd
|
||||
; CHECK: tnaget
|
||||
%v26 = call i32 @llvm.mblaze.fsl.tncget(i32 1)
|
||||
; CHECK-NOT: tncgetd
|
||||
; CHECK: tncget
|
||||
%v27 = call i32 @llvm.mblaze.fsl.tncaget(i32 1)
|
||||
; CHECK-NOT: tncagetd
|
||||
; CHECK: tncaget
|
||||
%v28 = call i32 @llvm.mblaze.fsl.tneget(i32 1)
|
||||
; CHECK-NOT: tnegetd
|
||||
; CHECK: tneget
|
||||
%v29 = call i32 @llvm.mblaze.fsl.tneaget(i32 1)
|
||||
; CHECK-NOT: tneagetd
|
||||
; CHECK: tneaget
|
||||
%v30 = call i32 @llvm.mblaze.fsl.tnecget(i32 1)
|
||||
; CHECK-NOT: tnecgetd
|
||||
; CHECK: tnecget
|
||||
%v31 = call i32 @llvm.mblaze.fsl.tnecaget(i32 1)
|
||||
; CHECK-NOT: tnecagetd
|
||||
; CHECK: tnecaget
|
||||
ret void
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define void @putfsl(i32 %value, i32 %port) {
|
||||
; CHECK-LABEL: putfsl:
|
||||
call void @llvm.mblaze.fsl.put(i32 %value, i32 %port)
|
||||
; CHECK: putd
|
||||
call void @llvm.mblaze.fsl.aput(i32 %value, i32 %port)
|
||||
; CHECK-NEXT: aputd
|
||||
call void @llvm.mblaze.fsl.cput(i32 %value, i32 %port)
|
||||
; CHECK-NEXT: cputd
|
||||
call void @llvm.mblaze.fsl.caput(i32 %value, i32 %port)
|
||||
; CHECK-NEXT: caputd
|
||||
call void @llvm.mblaze.fsl.nput(i32 %value, i32 %port)
|
||||
; CHECK-NEXT: nputd
|
||||
call void @llvm.mblaze.fsl.naput(i32 %value, i32 %port)
|
||||
; CHECK-NEXT: naputd
|
||||
call void @llvm.mblaze.fsl.ncput(i32 %value, i32 %port)
|
||||
; CHECK-NEXT: ncputd
|
||||
call void @llvm.mblaze.fsl.ncaput(i32 %value, i32 %port)
|
||||
; CHECK-NEXT: ncaputd
|
||||
call void @llvm.mblaze.fsl.tput(i32 %port)
|
||||
; CHECK-NEXT: tputd
|
||||
call void @llvm.mblaze.fsl.taput(i32 %port)
|
||||
; CHECK-NEXT: taputd
|
||||
call void @llvm.mblaze.fsl.tcput(i32 %port)
|
||||
; CHECK-NEXT: tcputd
|
||||
call void @llvm.mblaze.fsl.tcaput(i32 %port)
|
||||
; CHECK-NEXT: tcaputd
|
||||
call void @llvm.mblaze.fsl.tnput(i32 %port)
|
||||
; CHECK-NEXT: tnputd
|
||||
call void @llvm.mblaze.fsl.tnaput(i32 %port)
|
||||
; CHECK-NEXT: tnaputd
|
||||
call void @llvm.mblaze.fsl.tncput(i32 %port)
|
||||
; CHECK-NEXT: tncputd
|
||||
call void @llvm.mblaze.fsl.tncaput(i32 %port)
|
||||
; CHECK-NEXT: tncaputd
|
||||
ret void
|
||||
; CHECK: rtsd
|
||||
}
|
||||
|
||||
define void @putfsl_const(i32 %value) {
|
||||
; CHECK-LABEL: putfsl_const:
|
||||
call void @llvm.mblaze.fsl.put(i32 %value, i32 1)
|
||||
; CHECK-NOT: putd
|
||||
; CHECK: put
|
||||
call void @llvm.mblaze.fsl.aput(i32 %value, i32 1)
|
||||
; CHECK-NOT: aputd
|
||||
; CHECK: aput
|
||||
call void @llvm.mblaze.fsl.cput(i32 %value, i32 1)
|
||||
; CHECK-NOT: cputd
|
||||
; CHECK: cput
|
||||
call void @llvm.mblaze.fsl.caput(i32 %value, i32 1)
|
||||
; CHECK-NOT: caputd
|
||||
; CHECK: caput
|
||||
call void @llvm.mblaze.fsl.nput(i32 %value, i32 1)
|
||||
; CHECK-NOT: nputd
|
||||
; CHECK: nput
|
||||
call void @llvm.mblaze.fsl.naput(i32 %value, i32 1)
|
||||
; CHECK-NOT: naputd
|
||||
; CHECK: naput
|
||||
call void @llvm.mblaze.fsl.ncput(i32 %value, i32 1)
|
||||
; CHECK-NOT: ncputd
|
||||
; CHECK: ncput
|
||||
call void @llvm.mblaze.fsl.ncaput(i32 %value, i32 1)
|
||||
; CHECK-NOT: ncaputd
|
||||
; CHECK: ncaput
|
||||
call void @llvm.mblaze.fsl.tput(i32 1)
|
||||
; CHECK-NOT: tputd
|
||||
; CHECK: tput
|
||||
call void @llvm.mblaze.fsl.taput(i32 1)
|
||||
; CHECK-NOT: taputd
|
||||
; CHECK: taput
|
||||
call void @llvm.mblaze.fsl.tcput(i32 1)
|
||||
; CHECK-NOT: tcputd
|
||||
; CHECK: tcput
|
||||
call void @llvm.mblaze.fsl.tcaput(i32 1)
|
||||
; CHECK-NOT: tcaputd
|
||||
; CHECK: tcaput
|
||||
call void @llvm.mblaze.fsl.tnput(i32 1)
|
||||
; CHECK-NOT: tnputd
|
||||
; CHECK: tnput
|
||||
call void @llvm.mblaze.fsl.tnaput(i32 1)
|
||||
; CHECK-NOT: tnaputd
|
||||
; CHECK: tnaput
|
||||
call void @llvm.mblaze.fsl.tncput(i32 1)
|
||||
; CHECK-NOT: tncputd
|
||||
; CHECK: tncput
|
||||
call void @llvm.mblaze.fsl.tncaput(i32 1)
|
||||
; CHECK-NOT: tncaputd
|
||||
; CHECK: tncaput
|
||||
ret void
|
||||
; CHECK: rtsd
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
; Ensure that all immediate values that are 32-bits or less can be loaded
|
||||
; using a single instruction and that immediate values 64-bits or less can
|
||||
; be loaded using two instructions.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck %s
|
||||
; RUN: llc < %s -march=mblaze -mattr=+fpu | FileCheck -check-prefix=FPU %s
|
||||
|
||||
define i8 @retimm_i8() {
|
||||
; CHECK-LABEL: retimm_i8:
|
||||
; CHECK: rtsd
|
||||
; CHECK-NEXT: add
|
||||
; FPU-LABEL: retimm_i8:
|
||||
; FPU: rtsd
|
||||
; FPU-NEXT: add
|
||||
ret i8 123
|
||||
}
|
||||
|
||||
define i16 @retimm_i16() {
|
||||
; CHECK-LABEL: retimm_i16:
|
||||
; CHECK: rtsd
|
||||
; CHECK-NEXT: add
|
||||
; FPU-LABEL: retimm_i16:
|
||||
; FPU: rtsd
|
||||
; FPU-NEXT: add
|
||||
ret i16 31212
|
||||
}
|
||||
|
||||
define i32 @retimm_i32() {
|
||||
; CHECK-LABEL: retimm_i32:
|
||||
; CHECK: add
|
||||
; CHECK-NEXT: rtsd
|
||||
; FPU-LABEL: retimm_i32:
|
||||
; FPU: add
|
||||
; FPU-NEXT: rtsd
|
||||
ret i32 2938128
|
||||
}
|
||||
|
||||
define i64 @retimm_i64() {
|
||||
; CHECK-LABEL: retimm_i64:
|
||||
; CHECK: add
|
||||
; CHECK-NEXT: rtsd
|
||||
; CHECK-NEXT: add
|
||||
; FPU-LABEL: retimm_i64:
|
||||
; FPU: add
|
||||
; FPU-NEXT: rtsd
|
||||
; FPU-NEXT: add
|
||||
ret i64 94581823
|
||||
}
|
||||
|
||||
define float @retimm_float() {
|
||||
; CHECK-LABEL: retimm_float:
|
||||
; CHECK: add
|
||||
; CHECK-NEXT: rtsd
|
||||
; FPU-LABEL: retimm_float:
|
||||
; FPU: or
|
||||
; FPU-NEXT: rtsd
|
||||
ret float 12.0
|
||||
}
|
||||
|
||||
define double @retimm_double() {
|
||||
; CHECK-LABEL: retimm_double:
|
||||
; CHECK: add
|
||||
; CHECK-NEXT: add
|
||||
; CHECK-NEXT: rtsd
|
||||
; FPU-LABEL: retimm_double:
|
||||
; FPU: add
|
||||
; FPU-NEXT: add
|
||||
; FPU-NEXT: rtsd
|
||||
ret double 598382.39283873
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
; Ensure that the MBlaze interrupt_handler calling convention (cc73) is handled
|
||||
; correctly correctly by the MBlaze backend.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck %s
|
||||
|
||||
@.str = private constant [28 x i8] c"The interrupt has gone off\0A\00"
|
||||
@_interrupt_handler = alias void ()* @myintr
|
||||
|
||||
define cc73 void @myintr() nounwind noinline {
|
||||
; CHECK-LABEL: myintr:
|
||||
; CHECK: swi r3, r1
|
||||
; CHECK: swi r4, r1
|
||||
; CHECK: swi r5, r1
|
||||
; CHECK: swi r6, r1
|
||||
; CHECK: swi r7, r1
|
||||
; CHECK: swi r8, r1
|
||||
; CHECK: swi r9, r1
|
||||
; CHECK: swi r10, r1
|
||||
; CHECK: swi r11, r1
|
||||
; CHECK: swi r12, r1
|
||||
; CHECK: swi r17, r1
|
||||
; CHECK: swi r18, r1
|
||||
; CHECK: mfs r11, rmsr
|
||||
; CHECK: swi r11, r1
|
||||
entry:
|
||||
%call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([28 x i8]* @.str, i32 0, i32 0))
|
||||
ret void
|
||||
|
||||
; CHECK: lwi r11, r1
|
||||
; CHECK: mts rmsr, r11
|
||||
; CHECK: lwi r18, r1
|
||||
; CHECK: lwi r17, r1
|
||||
; CHECK: lwi r12, r1
|
||||
; CHECK: lwi r11, r1
|
||||
; CHECK: lwi r10, r1
|
||||
; CHECK: lwi r9, r1
|
||||
; CHECK: lwi r8, r1
|
||||
; CHECK: lwi r7, r1
|
||||
; CHECK: lwi r6, r1
|
||||
; CHECK: lwi r5, r1
|
||||
; CHECK: lwi r4, r1
|
||||
; CHECK: lwi r3, r1
|
||||
; CHECK: rtid r14, 0
|
||||
}
|
||||
|
||||
; CHECK: .globl _interrupt_handler
|
||||
; CHECK: _interrupt_handler = myintr
|
||||
declare i32 @printf(i8*, ...)
|
@ -1,79 +0,0 @@
|
||||
; Ensure that jump tables can be handled by the mblaze backend. The
|
||||
; jump table should be lowered to a "br" instruction using one of the
|
||||
; available registers.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck %s
|
||||
|
||||
define i32 @jmptable(i32 %arg)
|
||||
{
|
||||
; CHECK-LABEL: jmptable:
|
||||
switch i32 %arg, label %DEFAULT [ i32 0, label %L0
|
||||
i32 1, label %L1
|
||||
i32 2, label %L2
|
||||
i32 3, label %L3
|
||||
i32 4, label %L4
|
||||
i32 5, label %L5
|
||||
i32 6, label %L6
|
||||
i32 7, label %L7
|
||||
i32 8, label %L8
|
||||
i32 9, label %L9 ]
|
||||
|
||||
; CHECK: lw [[REG:r[0-9]*]]
|
||||
; CHECK: brad [[REG]]
|
||||
L0:
|
||||
%var0 = add i32 %arg, 0
|
||||
br label %DONE
|
||||
|
||||
L1:
|
||||
%var1 = add i32 %arg, 1
|
||||
br label %DONE
|
||||
|
||||
L2:
|
||||
%var2 = add i32 %arg, 2
|
||||
br label %DONE
|
||||
|
||||
L3:
|
||||
%var3 = add i32 %arg, 3
|
||||
br label %DONE
|
||||
|
||||
L4:
|
||||
%var4 = add i32 %arg, 4
|
||||
br label %DONE
|
||||
|
||||
L5:
|
||||
%var5 = add i32 %arg, 5
|
||||
br label %DONE
|
||||
|
||||
L6:
|
||||
%var6 = add i32 %arg, 6
|
||||
br label %DONE
|
||||
|
||||
L7:
|
||||
%var7 = add i32 %arg, 7
|
||||
br label %DONE
|
||||
|
||||
L8:
|
||||
%var8 = add i32 %arg, 8
|
||||
br label %DONE
|
||||
|
||||
L9:
|
||||
%var9 = add i32 %arg, 9
|
||||
br label %DONE
|
||||
|
||||
DEFAULT:
|
||||
unreachable
|
||||
|
||||
DONE:
|
||||
%rval = phi i32 [ %var0, %L0 ],
|
||||
[ %var1, %L1 ],
|
||||
[ %var2, %L2 ],
|
||||
[ %var3, %L3 ],
|
||||
[ %var4, %L4 ],
|
||||
[ %var5, %L5 ],
|
||||
[ %var6, %L6 ],
|
||||
[ %var7, %L7 ],
|
||||
[ %var8, %L8 ],
|
||||
[ %var9, %L9 ]
|
||||
ret i32 %rval
|
||||
; CHECK: rtsd
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
config.suffixes = ['.ll', '.c', '.cpp', '.test']
|
||||
|
||||
targets = set(config.root.targets_to_build.split())
|
||||
if not 'MBlaze' in targets:
|
||||
config.unsupported = True
|
||||
|
@ -1,44 +0,0 @@
|
||||
; Test some complicated looping constructs to ensure that they
|
||||
; compile successfully and that some sort of branching is used
|
||||
; in the resulting code.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s
|
||||
|
||||
declare i32 @printf(i8*, ...)
|
||||
@MSG = internal constant [19 x i8] c"Message: %d %d %d\0A\00"
|
||||
|
||||
define i32 @loop(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: loop:
|
||||
entry:
|
||||
br label %loop_outer
|
||||
|
||||
loop_outer:
|
||||
%outer.0 = phi i32 [ 0, %entry ], [ %outer.2, %loop_outer_finish ]
|
||||
br label %loop_inner
|
||||
|
||||
loop_inner:
|
||||
%inner.0 = phi i32 [ %a, %loop_outer ], [ %inner.3, %loop_inner_finish ]
|
||||
%inner.1 = phi i32 [ %b, %loop_outer ], [ %inner.4, %loop_inner_finish ]
|
||||
%inner.2 = phi i32 [ 0, %loop_outer ], [ %inner.5, %loop_inner_finish ]
|
||||
%inner.3 = add i32 %inner.0, %inner.1
|
||||
%inner.4 = mul i32 %inner.2, 11
|
||||
br label %loop_inner_finish
|
||||
|
||||
loop_inner_finish:
|
||||
%inner.5 = add i32 %inner.2, 1
|
||||
call i32 (i8*,...)* @printf( i8* getelementptr([19 x i8]* @MSG,i32 0,i32 0),
|
||||
i32 %inner.0, i32 %inner.1, i32 %inner.2 )
|
||||
|
||||
%inner.6 = icmp eq i32 %inner.5, 100
|
||||
; CHECK: cmp [[REG:r[0-9]*]]
|
||||
|
||||
br i1 %inner.6, label %loop_inner, label %loop_outer_finish
|
||||
; CHECK: {{beqid|bneid}} [[REG]]
|
||||
|
||||
loop_outer_finish:
|
||||
%outer.1 = add i32 %outer.0, 1
|
||||
%outer.2 = urem i32 %outer.1, 1500
|
||||
br label %loop_outer
|
||||
; CHECK: br
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
; Ensure that multiplication is lowered to function calls when the multiplier
|
||||
; unit is not available in the hardware and that function calls are not used
|
||||
; when the multiplier unit is available in the hardware.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
|
||||
; RUN: llc < %s -march=mblaze -mattr=+mul | FileCheck -check-prefix=MUL %s
|
||||
|
||||
define i8 @test_i8(i8 %a, i8 %b) {
|
||||
; FUN-LABEL: test_i8:
|
||||
; MUL-LABEL: test_i8:
|
||||
|
||||
%tmp.1 = mul i8 %a, %b
|
||||
; FUN-NOT: mul
|
||||
; FUN: brlid
|
||||
; MUL-NOT: brlid
|
||||
|
||||
ret i8 %tmp.1
|
||||
; FUN: rtsd
|
||||
; MUL: rtsd
|
||||
; MUL: mul
|
||||
}
|
||||
|
||||
define i16 @test_i16(i16 %a, i16 %b) {
|
||||
; FUN-LABEL: test_i16:
|
||||
; MUL-LABEL: test_i16:
|
||||
|
||||
%tmp.1 = mul i16 %a, %b
|
||||
; FUN-NOT: mul
|
||||
; FUN: brlid
|
||||
; MUL-NOT: brlid
|
||||
|
||||
ret i16 %tmp.1
|
||||
; FUN: rtsd
|
||||
; MUL: rtsd
|
||||
; MUL: mul
|
||||
}
|
||||
|
||||
define i32 @test_i32(i32 %a, i32 %b) {
|
||||
; FUN-LABEL: test_i32:
|
||||
; MUL-LABEL: test_i32:
|
||||
|
||||
%tmp.1 = mul i32 %a, %b
|
||||
; FUN-NOT: mul
|
||||
; FUN: brlid
|
||||
; MUL-NOT: brlid
|
||||
|
||||
ret i32 %tmp.1
|
||||
; FUN: rtsd
|
||||
; MUL: rtsd
|
||||
; MUL: mul
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
; Ensure that multiplication is lowered to function calls when the 64-bit
|
||||
; multiplier unit is not available in the hardware and that function calls
|
||||
; are not used when the 64-bit multiplier unit is available in the hardware.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
|
||||
; RUN: llc < %s -march=mblaze -mattr=+mul,+mul64 | \
|
||||
; RUN: FileCheck -check-prefix=MUL %s
|
||||
|
||||
define i64 @test_i64(i64 %a, i64 %b) {
|
||||
; FUN-LABEL: test_i64:
|
||||
; MUL-LABEL: test_i64:
|
||||
|
||||
%tmp.1 = mul i64 %a, %b
|
||||
; FUN-NOT: mul
|
||||
; FUN: brlid
|
||||
; MUL-NOT: brlid
|
||||
; MUL: mulh
|
||||
; MUL: mul
|
||||
|
||||
ret i64 %tmp.1
|
||||
; FUN: rtsd
|
||||
; MUL: rtsd
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
; Ensure that the select instruction is supported and is lowered to
|
||||
; some sort of branch instruction.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck %s
|
||||
|
||||
define i32 @testsel(i32 %a, i32 %b)
|
||||
{
|
||||
; CHECK-LABEL: testsel:
|
||||
%tmp.1 = icmp eq i32 %a, %b
|
||||
; CHECK: cmp
|
||||
%tmp.2 = select i1 %tmp.1, i32 %a, i32 %b
|
||||
; CHECK: {{bne|beq}}
|
||||
ret i32 %tmp.2
|
||||
; CHECK: rtsd
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
; Ensure that shifts are lowered to loops when the barrel shifter unit is
|
||||
; not available in the hardware and that loops are not used when the
|
||||
; barrel shifter unit is available in the hardware.
|
||||
;
|
||||
; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s
|
||||
; RUN: llc < %s -march=mblaze -mattr=+barrel | FileCheck -check-prefix=SHT %s
|
||||
|
||||
define i8 @test_i8(i8 %a, i8 %b) {
|
||||
; FUN-LABEL: test_i8:
|
||||
; SHT-LABEL: test_i8:
|
||||
|
||||
%tmp.1 = shl i8 %a, %b
|
||||
; FUN: andi
|
||||
; FUN: add
|
||||
; FUN: bnei
|
||||
; SHT-NOT: bnei
|
||||
|
||||
ret i8 %tmp.1
|
||||
; FUN: rtsd
|
||||
; SHT: rtsd
|
||||
; FUN-NOT: bsll
|
||||
; SHT-NEXT: bsll
|
||||
}
|
||||
|
||||
define i8 @testc_i8(i8 %a, i8 %b) {
|
||||
; FUN-LABEL: testc_i8:
|
||||
; SHT-LABEL: testc_i8:
|
||||
|
||||
%tmp.1 = shl i8 %a, 5
|
||||
; FUN: andi
|
||||
; FUN: add
|
||||
; FUN: bnei
|
||||
; SHT-NOT: andi
|
||||
; SHT-NOT: add
|
||||
; SHT-NOT: bnei
|
||||
|
||||
ret i8 %tmp.1
|
||||
; FUN: rtsd
|
||||
; SHT: rtsd
|
||||
; FUN-NOT: bsll
|
||||
; SHT-NEXT: bslli
|
||||
}
|
||||
|
||||
define i16 @test_i16(i16 %a, i16 %b) {
|
||||
; FUN-LABEL: test_i16:
|
||||
; SHT-LABEL: test_i16:
|
||||
|
||||
%tmp.1 = shl i16 %a, %b
|
||||
; FUN: andi
|
||||
; FUN: add
|
||||
; FUN: bnei
|
||||
; SHT-NOT: bnei
|
||||
|
||||
ret i16 %tmp.1
|
||||
; FUN: rtsd
|
||||
; SHT: rtsd
|
||||
; FUN-NOT: bsll
|
||||
; SHT-NEXT: bsll
|
||||
}
|
||||
|
||||
define i16 @testc_i16(i16 %a, i16 %b) {
|
||||
; FUN-LABEL: testc_i16:
|
||||
; SHT-LABEL: testc_i16:
|
||||
|
||||
%tmp.1 = shl i16 %a, 5
|
||||
; FUN: andi
|
||||
; FUN: add
|
||||
; FUN: bnei
|
||||
; SHT-NOT: andi
|
||||
; SHT-NOT: add
|
||||
; SHT-NOT: bnei
|
||||
|
||||
ret i16 %tmp.1
|
||||
; FUN: rtsd
|
||||
; SHT: rtsd
|
||||
; FUN-NOT: bsll
|
||||
; SHT-NEXT: bslli
|
||||
}
|
||||
|
||||
define i32 @test_i32(i32 %a, i32 %b) {
|
||||
; FUN-LABEL: test_i32:
|
||||
; SHT-LABEL: test_i32:
|
||||
|
||||
%tmp.1 = shl i32 %a, %b
|
||||
; FUN: andi
|
||||
; FUN: add
|
||||
; FUN: bnei
|
||||
; SHT-NOT: andi
|
||||
; SHT-NOT: bnei
|
||||
|
||||
ret i32 %tmp.1
|
||||
; FUN: rtsd
|
||||
; SHT: rtsd
|
||||
; FUN-NOT: bsll
|
||||
; SHT-NEXT: bsll
|
||||
}
|
||||
|
||||
define i32 @testc_i32(i32 %a, i32 %b) {
|
||||
; FUN-LABEL: testc_i32:
|
||||
; SHT-LABEL: testc_i32:
|
||||
|
||||
%tmp.1 = shl i32 %a, 5
|
||||
; FUN: andi
|
||||
; FUN: add
|
||||
; FUN: bnei
|
||||
; SHT-NOT: andi
|
||||
; SHT-NOT: add
|
||||
; SHT-NOT: bnei
|
||||
|
||||
ret i32 %tmp.1
|
||||
; FUN: rtsd
|
||||
; SHT: rtsd
|
||||
; FUN-NOT: bsll
|
||||
; SHT-NEXT: bslli
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user