[clang] [compiler-rt] [llvm] Add SuperH (1-4a) target (PR #181287)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 6 05:42:00 PDT 2026
https://github.com/LunaTheFoxgirl updated https://github.com/llvm/llvm-project/pull/181287
>From 63a5058d7763eaf2d9be5db4ff04d5f8dd30664d Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 13 Feb 2026 02:37:18 +0100
Subject: [PATCH 01/39] sh4: initial commit
---
llvm/CMakeLists.txt | 1 +
llvm/lib/Target/SuperH/CMakeLists.txt | 25 ++++
.../Target/SuperH/MCTargetDesc/CMakeLists.txt | 12 ++
.../MCTargetDesc/SuperHMCTargetDesc.cpp | 34 ++++++
.../SuperH/MCTargetDesc/SuperHMCTargetDesc.h | 38 ++++++
llvm/lib/Target/SuperH/SuperH.td | 59 +++++++++
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 21 ++++
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 21 ++++
llvm/lib/Target/SuperH/SuperHRegisterInfo.td | 113 ++++++++++++++++++
llvm/lib/Target/SuperH/SuperHSchedule.td | 22 ++++
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 40 +++++++
llvm/lib/Target/SuperH/SuperHTargetMachine.h | 38 ++++++
.../Target/SuperH/TargetInfo/CMakeLists.txt | 10 ++
.../SuperH/TargetInfo/SuperHTargetInfo.cpp | 23 ++++
.../SuperH/TargetInfo/SuperHTargetInfo.h | 20 ++++
15 files changed, 477 insertions(+)
create mode 100644 llvm/lib/Target/SuperH/CMakeLists.txt
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
create mode 100644 llvm/lib/Target/SuperH/SuperH.td
create mode 100644 llvm/lib/Target/SuperH/SuperHInstrFormats.td
create mode 100644 llvm/lib/Target/SuperH/SuperHInstrInfo.td
create mode 100644 llvm/lib/Target/SuperH/SuperHRegisterInfo.td
create mode 100644 llvm/lib/Target/SuperH/SuperHSchedule.td
create mode 100644 llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHTargetMachine.h
create mode 100644 llvm/lib/Target/SuperH/TargetInfo/CMakeLists.txt
create mode 100644 llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
create mode 100644 llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.h
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 2e2c269c0abbc..7b36ea47d04c9 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -540,6 +540,7 @@ set(LLVM_ALL_EXPERIMENTAL_TARGETS
DirectX
M68k
Xtensa
+ SuperH
)
# List of targets with JIT support:
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
new file mode 100644
index 0000000000000..a12dcbc2e101d
--- /dev/null
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -0,0 +1,25 @@
+add_llvm_component_group(SuperH)
+
+set(LLVM_TARGET_DEFINITIONS SuperH.td)
+
+# add_public_tablegen_target(SuperHCommonTableGen)
+
+add_llvm_target(SuperHCodeGen
+ SuperHTargetMachine.cpp
+
+ LINK_COMPONENTS
+ AsmPrinter
+ CodeGen
+ Core
+ MC
+ SelectionDAG
+ Support
+ Target
+ TargetParser
+
+ ADD_TO_COMPONENT
+ SuperH
+ )
+
+add_subdirectory(TargetInfo)
+add_subdirectory(MCTargetDesc)
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
new file mode 100644
index 0000000000000..a9a69ea22dc05
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_llvm_component_library(LLVMSuperHDesc
+ SuperHMCTargetDesc.cpp
+
+ LINK_COMPONENTS
+ MC
+ MCDisassembler
+ Support
+ TargetParser
+
+ ADD_TO_COMPONENT
+ SuperH
+)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
new file mode 100644
index 0000000000000..d7ac60efb4563
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
@@ -0,0 +1,34 @@
+//===-- SuperHMCTargetDesc.cpp - SuperH Target Descriptions ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file provides SuperH target specific descriptions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "SuperHMCTargetDesc.h"
+#include "TargetInfo/SuperHTargetInfo.h"
+
+#include "llvm/MC/MCELFStreamer.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+
+using namespace llvm;
+
+extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY
+void LLVMInitializeSuperHTargetMC() {
+
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
new file mode 100644
index 0000000000000..b1428a0b33366
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
@@ -0,0 +1,38 @@
+//===-- SuperHMCTargetDesc.h - SuperH Target Descriptions -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file provides SuperH specific target descriptions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCTARGETDESC_H
+#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCTARGETDESC_H
+
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCRegisterInfo;
+class MCSubtargetInfo;
+class MCRelocationInfo;
+class MCTargetOptions;
+class Target;
+class Triple;
+class StringRef;
+class raw_ostream;
+class raw_pwrite_stream;
+
+}
+
+#endif // LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCTARGETDESC_H
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
new file mode 100644
index 0000000000000..ea768a5b8dc9d
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -0,0 +1,59 @@
+//===- SuperH.td - Describe the SuperH Target Machine ------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Target-independent interfaces
+//===----------------------------------------------------------------------===//
+
+include "llvm/Target/Target.td"
+
+//===----------------------------------------------------------------------===//
+// SuperH Subtarget features
+//===----------------------------------------------------------------------===//
+
+
+//===----------------------------------------------------------------------===//
+// SuperH Processors
+//===----------------------------------------------------------------------===//
+
+include "SuperHSchedule.td"
+
+class Proc<string Name, list<SubtargetFeature> Features>
+ : ProcessorModel<Name, GenericSHModel, Features>;
+
+def : Proc<"generic", [ ]>;
+def : Proc<"sh1", []>;
+def : Proc<"sh2", []>;
+def : Proc<"sh3", []>;
+def : Proc<"sh4", []>;
+def : Proc<"sh4a", []>;
+
+//===----------------------------------------------------------------------===//
+// Register File Description
+//===----------------------------------------------------------------------===//
+
+include "SuperHRegisterInfo.td"
+
+//===----------------------------------------------------------------------===//
+// Instruction Descriptions
+//===----------------------------------------------------------------------===//
+
+// include "SuperHInstrInfo.td"
+
+def SuperHInstrInfo : InstrInfo;
+
+//===----------------------------------------------------------------------===//
+// Target Declaration
+//===----------------------------------------------------------------------===//
+
+def SuperH : Target {
+ let InstructionSet = SuperHInstrInfo;
+
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
new file mode 100644
index 0000000000000..d3bacb075c9ba
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -0,0 +1,21 @@
+//===-- SuperHInstrFormats.td - SuperH Instruction Formats ---------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+class SHInst<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : Instruction {
+ let Namespace = "SH";
+
+ dag OutOperandList = outs;
+ dag InOperandList = ins;
+ let AsmString = asmtr;
+ let Pattern = pattern;
+
+ field bits<16> Inst;
+ let Size = 2;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
new file mode 100644
index 0000000000000..a4451d7a502d5
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -0,0 +1,21 @@
+//===-- SuperHInstrInfo.td - Main SuperH Instruction Definition -*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes the SuperH instruction set, defining the instructions
+/// and properties of the instructions which are needed for code generation,
+/// machine code emission, and analysis.
+///
+//===----------------------------------------------------------------------===//
+
+include "SuperHInstrFormats.td"
+
+//===----------------------------------------------------------------------===//
+// SuperH Type Profiles
+//===----------------------------------------------------------------------===//
+
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
new file mode 100644
index 0000000000000..325d6520c1512
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -0,0 +1,113 @@
+//==-- SuperHRegisterInfo.td - SuperH register definitions ------*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes the SuperH Register file, defining the registers
+/// aliases between the registers, and the register classes built out of the
+/// registers.
+///
+//===----------------------------------------------------------------------===//
+
+// SuperH Registers
+class SHRegister<string N, bits<16> ENC,
+ list<Register> SUBREGS = [], list<SubRegIndex> SUBIDX,
+ list<string> ALTNAMES = []>
+ : Register<N, ALTNAMES> {
+ let Namespace = "SH";
+ let HWEncoding = ENC;
+ let SubRegs = SUBREGS;
+ let SubRegIndices = SUBIDX;
+}
+
+let Namespace = "SH" in {
+
+ // MAC registers
+ def sub_16bit_lo : SubRegIndex<16>;
+ def sub_16bit_hi : SubRegIndex<16, 16>;
+
+ // FP Registers
+ def sub_32bit_lo : SubRegIndex<32>;
+ def sub_32bit_hi : SubRegIndex<32, 32>;
+}
+
+//===----------------------------------------------------------------------===//
+// Registers
+//===----------------------------------------------------------------------===//
+
+let Namespace = "SH" in {
+
+ // GP Registers
+ def R0 : SHRegister<0, "r0>, DwarfRegNum<[ 0 ]>;
+ def R1 : SHRegister<1, "r1>, DwarfRegNum<[ 1 ]>;
+ def R2 : SHRegister<2, "r2>, DwarfRegNum<[ 2 ]>;
+ def R3 : SHRegister<3, "r3>, DwarfRegNum<[ 3 ]>;
+ def R4 : SHRegister<4, "r4>, DwarfRegNum<[ 4 ]>;
+ def R5 : SHRegister<5, "r5>, DwarfRegNum<[ 5 ]>;
+ def R6 : SHRegister<6, "r6>, DwarfRegNum<[ 6 ]>;
+ def R7 : SHRegister<7, "r7>, DwarfRegNum<[ 7 ]>;
+ def R8 : SHRegister<8, "r8>, DwarfRegNum<[ 8 ]>;
+ def R9 : SHRegister<9, "r9>, DwarfRegNum<[ 9 ]>;
+ def R10 : SHRegister<10, "r10>, DwarfRegNum<[ 10 ]>;
+ def R11 : SHRegister<11, "r11>, DwarfRegNum<[ 11 ]>;
+ def R12 : SHRegister<12, "r12>, DwarfRegNum<[ 12 ]>;
+ def R13 : SHRegister<13, "r13>, DwarfRegNum<[ 13 ]>;
+ def R14 : SHRegister<14, "r14, [ "fp" ]>, DwarfRegNum<[ 14 ]>;
+ def R15 : SHRegister<15, "r15, [ "sp" ]>, DwarfRegNum<[ 15 ]>;
+
+ // Control Registers
+ def SR : SHRegister<16, "sr">, DwarfRegNum<[ 22 ]>;
+ def GBR : SHRegister<17, "gbr">, DwarfRegNum<[ 18 ]>;
+ def VBR : SHRegister<18, "vbr">, DwarfRegNum<[ 19 ]>;
+
+ // System Registers
+ def MACH : SHRegister<19, "mach">, DwarfRegNum<[ 21 ]>;
+ def MACL : SHRegister<20, "macl">, DwarfRegNum<[ 21 ]>;
+ let SubRegIndices = [sub_16bit_lo, sub_16bit_hi] in {
+ def MAC : SHRegister<21, "mac", [], [MACL, MACH]>;
+ }
+ def PC : SHRegister<22, "pc">, DwarfRegNum<[ 16 ]>;
+ def PR : SHRegister<23, "pr">, DwarfRegNum<[ 17 ]>;
+
+ // FR Registers
+
+ // TODO: Add float registers
+}
+
+//===----------------------------------------------------------------------===//
+// Register Classes
+//===----------------------------------------------------------------------===//
+
+def GPR : RegisterClass<"SH", [i32], 32, (
+ add(
+ R0, R1, R2, R3, R4, R5, R6, R7, // Banked memory
+ R8, R9, R10, R11, R12, R13, R14, R15, // Non-banked memory.
+ )
+)>;
+
+// Control registers
+def CR : RegisterClass<"SH", [i32], 32, (add SR, GBR, VBR>) {
+ let CopyCost = -1;
+ let isAllocatable = 0;
+}
+
+// System registers.
+def SYSR : RegisterClass<"SH", [ i32 ], 32, (add MACH, MACL, PR, PC)> {
+ let CopyCost = -1;
+ let isAllocatable = 0;
+}
+
+// MAC register.
+def MACR : RegisterClass<"SH", [ i64 ], 64, (add MAC)> {
+ let CopyCost = -1;
+ let isAllocatable = 0;
+}
+
+def PCR : RegisterClass<"SH", [ i32 ], 32, (add PC)> {
+ let CopyCost = -1;
+ let isAllocatable = 0;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHSchedule.td b/llvm/lib/Target/SuperH/SuperHSchedule.td
new file mode 100644
index 0000000000000..fe0d13648349f
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHSchedule.td
@@ -0,0 +1,22 @@
+//===-- SuperHSchedule.td - SuperH Scheduling Definitions ------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains SuperH scheduler definitions.
+///
+//===----------------------------------------------------------------------===//
+
+/// SuperH Base Scheduling Model.
+class SuperHSchedModel : SchedMachineModel {
+ let LoadLatency = 4; // Word (Rn)
+ let HighLatency = 16; // Long ABS
+ let PostRAScheduler = 0;
+ let CompleteModel = 0;
+}
+
+def GenericSuperHModel : SuperHSchedModel;
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
new file mode 100644
index 0000000000000..91673573b22b2
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -0,0 +1,40 @@
+//===-- SuperHTargetMachine.cpp - Define TargetMachine for SuperH -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHTargetMachine.h"
+#include "TargetInfo/SuperHTargetInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Compiler.h"
+#include <optional>
+
+using namespace llvm;
+
+extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSuperHTarget() {
+ RegisterTargetMachine<SuperHTargetMachine> SH(getTheSuperHTarget());
+}
+
+SuperHTargetMachine::~SuperHTargetMachine() { }
+
+/// Create a SuperH architecture model.
+SuperHTargetMachine::SuperHTargetMachine(const Target &T, const Triple &TT,
+ StringRef CPU, StringRef FS,
+ const TargetOptions &Options,
+ std::optional<Reloc::Model> RM,
+ std::optional<CodeModel::Model> CM,
+ CodeGenOptLevel OL, bool JIT)
+ : CodeGenTargetMachineImpl(
+ T, TT.computeDataLayout(), TT, CPU, FS, Options,
+ RM.value_or(Reloc::Static), getEffectiveCodeModel(CM, CodeModel::Small),
+ OL) {
+
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.h b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
new file mode 100644
index 0000000000000..5da814b766f4a
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
@@ -0,0 +1,38 @@
+//===-- SuperHTargetMachine.h - Define TargetMachine for SuperH ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SuperH specific subclass of TargetMachine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPARC_SPARCTARGETMACHINE_H
+#define LLVM_LIB_TARGET_SPARC_SPARCTARGETMACHINE_H
+
+#include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
+#include "llvm/Target/TargetMachine.h"
+#include <optional>
+
+namespace llvm {
+
+class SuperHTargetMachine : public CodeGenTargetMachineImpl {
+private:
+
+protected:
+
+public:
+ SuperHTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
+ StringRef FS, const TargetOptions &Options,
+ std::optional<Reloc::Model> RM,
+ std::optional<CodeModel::Model> CM, CodeGenOptLevel OL,
+ bool JIT);
+ ~SuperHTargetMachine() override;
+
+};
+} // end namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/SuperH/TargetInfo/CMakeLists.txt b/llvm/lib/Target/SuperH/TargetInfo/CMakeLists.txt
new file mode 100644
index 0000000000000..73abb4dbba519
--- /dev/null
+++ b/llvm/lib/Target/SuperH/TargetInfo/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_llvm_component_library(LLVMSuperHInfo
+ SuperHTargetInfo.cpp
+
+ LINK_COMPONENTS
+ MC
+ Support
+
+ ADD_TO_COMPONENT
+ SuperH
+ )
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
new file mode 100644
index 0000000000000..b676f36dc8d55
--- /dev/null
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
@@ -0,0 +1,23 @@
+//===-- SuperHTargetInfo.cpp - SuperH Target Implementation -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TargetInfo/SuperHTargetInfo.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Compiler.h"
+using namespace llvm;
+
+Target &llvm::getTheSuperHTarget() {
+ static Target TheSuperHTarget;
+ return TheSuperHTarget;
+}
+
+extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY
+void LLVMInitializeSuperHTargetInfo() {
+ RegisterTarget<Triple::superh, /*HasJIT=*/false> X(getTheSuperHTarget(),
+ "sh", "SuperH", "SuperH");
+}
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.h b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.h
new file mode 100644
index 0000000000000..38b501e05d46e
--- /dev/null
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.h
@@ -0,0 +1,20 @@
+//===-- SuperHTargetInfo.h - SuperH Target Implementation ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_TARGETINFO_SUPERHTARGETINFO_H
+#define LLVM_LIB_TARGET_SUPERH_TARGETINFO_SUPERHTARGETINFO_H
+
+namespace llvm {
+
+class Target;
+
+Target &getTheSuperHTarget();
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SUPERH_TARGETINFO_SUPERHTARGETINFO_H
>From e31622952c80e4579aba246c32c29e514104d1af Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 29 May 2026 02:41:44 +0200
Subject: [PATCH 02/39] Add self to Maintainers.md
---
llvm/Maintainers.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/llvm/Maintainers.md b/llvm/Maintainers.md
index 1b84d12fa51f3..911a0e9674856 100644
--- a/llvm/Maintainers.md
+++ b/llvm/Maintainers.md
@@ -354,6 +354,11 @@ nigelp at xmos.com (email), [nigelp-xmos](https://github.com/nigelp-xmos) (GitHub)
Andrei Safronov \
andrei.safronov at espressif.com (email), [andreisfr](https://github.com/andreisfr) (GitHub)
+#### SuperH backend
+
+Luna Nielsen \
+luna at foxgirls.gay (email), [LunaTheFoxgirl](https://github.com/LunaTheFoxgirl) (GitHub)
+
### Libraries and shared infrastructure
#### ADT, Support
>From 5bdf0fb053af407aa5df9281c138a300e9e5ad0c Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 29 May 2026 05:14:53 +0200
Subject: [PATCH 03/39] Flesh out register file and target cpu
---
llvm/include/llvm/TargetParser/Triple.h | 1 +
llvm/lib/Target/SuperH/SuperH.td | 33 ++-
llvm/lib/Target/SuperH/SuperHRegisterInfo.td | 220 ++++++++++++------
.../SuperH/TargetInfo/SuperHTargetInfo.cpp | 2 +-
llvm/lib/TargetParser/Triple.cpp | 6 +
5 files changed, 187 insertions(+), 75 deletions(-)
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 7b24db121818f..25b35bb99edb7 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -79,6 +79,7 @@ class Triple {
riscv64, // RISC-V (64-bit, little endian): riscv64
riscv32be, // RISC-V (32-bit, big endian): riscv32be
riscv64be, // RISC-V (64-bit, big endian): riscv64be
+ sh, // SuperH: sh
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index ea768a5b8dc9d..cd7ef7e54f403 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -7,6 +7,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+// This is the top level entry point for the SuperH target.
+//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Target-independent interfaces
@@ -18,6 +20,24 @@ include "llvm/Target/Target.td"
// SuperH Subtarget features
//===----------------------------------------------------------------------===//
+def FeatureFPU : SubtargetFeature<"fpu", "HasFPU", "false",
+ "Enable FPU Support">;
+def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU", "true",
+ "Enable vector FPU instructions">;
+def FeatureSH1 : SubtargetFeature<"sh1", "SHArchVersion", "SH1",
+ "SH-1 ISA Support">;
+def FeatureSH2 : SubtargetFeature<"sh2", "SHArchVersion", "SH2",
+ "SH-2 ISA Support",
+ [FeatureSH1]>;
+def FeatureSH3 : SubtargetFeature<"sh3", "SHArchVersion", "SH3",
+ "SH-3 ISA Support",
+ [FeatureSH1, FeatureSH2]>;
+def FeatureSH4 : SubtargetFeature<"sh4", "SHArchVersion", "SH3",
+ "SH-4 ISA Support",
+ [FeatureSH1, FeatureSH2, FeatureSH3, FeatureFPU]>;
+def FeatureSH4A : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
+ "SH-4A ISA Support",
+ [FeatureSH1, FeatureSH2, FeatureSH3, FeatureSH4, FeatureFPU]>;
//===----------------------------------------------------------------------===//
// SuperH Processors
@@ -28,12 +48,12 @@ include "SuperHSchedule.td"
class Proc<string Name, list<SubtargetFeature> Features>
: ProcessorModel<Name, GenericSHModel, Features>;
-def : Proc<"generic", [ ]>;
-def : Proc<"sh1", []>;
-def : Proc<"sh2", []>;
-def : Proc<"sh3", []>;
-def : Proc<"sh4", []>;
-def : Proc<"sh4a", []>;
+def : Proc<"generic", [FeatureSH4]>;
+def : Proc<"sh1", [FeatureSH1]>;
+def : Proc<"sh2", [FeatureSH2]>;
+def : Proc<"sh3", [FeatureSH3]>;
+def : Proc<"sh4", [FeatureSH4]>;
+def : Proc<"sh4a", [FeatureSH4A]>;
//===----------------------------------------------------------------------===//
// Register File Description
@@ -55,5 +75,4 @@ def SuperHInstrInfo : InstrInfo;
def SuperH : Target {
let InstructionSet = SuperHInstrInfo;
-
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index 325d6520c1512..abf4cbfcc3ba2 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -13,101 +13,187 @@
///
//===----------------------------------------------------------------------===//
-// SuperH Registers
-class SHRegister<string N, bits<16> ENC,
- list<Register> SUBREGS = [], list<SubRegIndex> SUBIDX,
- list<string> ALTNAMES = []>
- : Register<N, ALTNAMES> {
- let Namespace = "SH";
- let HWEncoding = ENC;
- let SubRegs = SUBREGS;
- let SubRegIndices = SUBIDX;
-}
+//===----------------------------------------------------------------------===//
+// Declarations that describe the SuperH register file
+//===----------------------------------------------------------------------===//
let Namespace = "SH" in {
+ def sub_64_lo : SubRegIndex<64>;
+ def sub_64_hi : SubRegIndex<64, 64>;
+ def sub_32_lo : SubRegIndex<32>;
+ def sub_32_hi : SubRegIndex<32, 32>;
+
+ // Vector Registers
+ def sub_fv_x : SubRegIndex<32>;
+ def sub_fv_y : SubRegIndex<32, 32>;
+ def sub_fv_z : SubRegIndex<32, 64>;
+ def sub_fv_w : SubRegIndex<32, 96>;
+
+ // Matrix Register
+}
+
+class Unallocatable {
+ int CopyCost = -1;
+ bit isAllocatable = false;
+}
+
+class SHReg<bits<16> Enc, string n> : Register<n> {
+ let HWEncoding = Enc;
+ let Namespace = "SH";
+}
- // MAC registers
- def sub_16bit_lo : SubRegIndex<16>;
- def sub_16bit_hi : SubRegIndex<16, 16>;
+class SHRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs>
+ : RegisterWithSubRegs<n, subregs> {
+ let HWEncoding = Enc;
+ let Namespace = "SH";
+}
+
+// SH General Purpose Registers.
+class GPRReg<bits<16> Enc, string n> : MipsReg<Enc, n>;
+
+// Control Registers
+class CtrlReg<bits<16> Enc, string n> : MipsReg<Enc, n>;
+
+// SH System Registers.
+class SysReg<bits<16> Enc, string n> : MipsReg<Enc, n>;
- // FP Registers
- def sub_32bit_lo : SubRegIndex<32>;
- def sub_32bit_hi : SubRegIndex<32, 32>;
+// 32-bit floating point registers
+class FRReg<bits<16> Enc, string n> : SHReg<Enc, n>;
+
+// 64-bit (alias) FPU registers
+class DRReg<bits<16> Enc, string n, list<Register> subregs>
+ : SHRegWithSubRegs<Enc, n, subregs> {
+ let SubRegIndices = [sub_32_lo, sub_32_hi];
+ let CoveredBySubRegs = 1;
+}
+
+// 32-bit (alias) VFPU registers
+class FVReg<bits<16> Enc, string n, list<Register> subregs>
+ : SHRegWithSubRegs<Enc, n, subregs> {
+ let SubRegIndices = [sub_fv_x, sub_fv_y, sub_fv_z, sub_fv_w];
+ let CoveredBySubRegs = 1;
}
+// 512-bit Matrix Register
+class MTRXReg<bits<16> Enc, string n> : SHReg<Enc, n>;
+
//===----------------------------------------------------------------------===//
// Registers
//===----------------------------------------------------------------------===//
let Namespace = "SH" in {
- // GP Registers
- def R0 : SHRegister<0, "r0>, DwarfRegNum<[ 0 ]>;
- def R1 : SHRegister<1, "r1>, DwarfRegNum<[ 1 ]>;
- def R2 : SHRegister<2, "r2>, DwarfRegNum<[ 2 ]>;
- def R3 : SHRegister<3, "r3>, DwarfRegNum<[ 3 ]>;
- def R4 : SHRegister<4, "r4>, DwarfRegNum<[ 4 ]>;
- def R5 : SHRegister<5, "r5>, DwarfRegNum<[ 5 ]>;
- def R6 : SHRegister<6, "r6>, DwarfRegNum<[ 6 ]>;
- def R7 : SHRegister<7, "r7>, DwarfRegNum<[ 7 ]>;
- def R8 : SHRegister<8, "r8>, DwarfRegNum<[ 8 ]>;
- def R9 : SHRegister<9, "r9>, DwarfRegNum<[ 9 ]>;
- def R10 : SHRegister<10, "r10>, DwarfRegNum<[ 10 ]>;
- def R11 : SHRegister<11, "r11>, DwarfRegNum<[ 11 ]>;
- def R12 : SHRegister<12, "r12>, DwarfRegNum<[ 12 ]>;
- def R13 : SHRegister<13, "r13>, DwarfRegNum<[ 13 ]>;
- def R14 : SHRegister<14, "r14, [ "fp" ]>, DwarfRegNum<[ 14 ]>;
- def R15 : SHRegister<15, "r15, [ "sp" ]>, DwarfRegNum<[ 15 ]>;
+ // General Purpose Registers
+ def R0 : SHGPRReg<0, "r0">, DwarfRegNum<[0]>;
+ def R1 : SHGPRReg<1, "r1">, DwarfRegNum<[1]>;
+ def R2 : SHGPRReg<2, "r2">, DwarfRegNum<[2]>;
+ def R3 : SHGPRReg<3, "r3">, DwarfRegNum<[3]>;
+ def R4 : SHGPRReg<4, "r4">, DwarfRegNum<[4]>;
+ def R5 : SHGPRReg<5, "r5">, DwarfRegNum<[5]>;
+ def R6 : SHGPRReg<6, "r6">, DwarfRegNum<[6]>;
+ def R7 : SHGPRReg<7, "r7">, DwarfRegNum<[7]>;
+ def R8 : SHGPRReg<8, "r8">, DwarfRegNum<[8]>;
+ def R9 : SHGPRReg<9, "r9">, DwarfRegNum<[9]>;
+ def R10 : SHGPRReg<10, "r10">, DwarfRegNum<[10]>;
+ def R11 : SHGPRReg<11, "r11">, DwarfRegNum<[11]>;
+ def R12 : SHGPRReg<12, "r12">, DwarfRegNum<[12]>;
+ def R13 : SHGPRReg<13, "r13">, DwarfRegNum<[13]>;
+ def R14 : SHGPRReg<14, "r14">, DwarfRegNum<[14]>;
+ def R15 : SHGPRReg<15, "r15">, DwarfRegNum<[15]>;
// Control Registers
- def SR : SHRegister<16, "sr">, DwarfRegNum<[ 22 ]>;
- def GBR : SHRegister<17, "gbr">, DwarfRegNum<[ 18 ]>;
- def VBR : SHRegister<18, "vbr">, DwarfRegNum<[ 19 ]>;
+ def SR : CtrlReg<0, "sr">; // Status Register
+ def GBR : CtrlReg<0, "gbr"; // Global Base Register
+ def VBR : CtrlReg<0, "vbr">; // Vector Base Register
+ def SGR : CtrlReg<0, "sgr">; // Saved General Register
+ def DBR : CtrlReg<0, "dbr">; // Debug Base Register
+ def SSR : CtrlReg<0, "ssr">; // Saved Status Register
+ def SPC : CtrlReg<0, "spc">; // Saved Program Counter
// System Registers
- def MACH : SHRegister<19, "mach">, DwarfRegNum<[ 21 ]>;
- def MACL : SHRegister<20, "macl">, DwarfRegNum<[ 21 ]>;
- let SubRegIndices = [sub_16bit_lo, sub_16bit_hi] in {
- def MAC : SHRegister<21, "mac", [], [MACL, MACH]>;
- }
- def PC : SHRegister<22, "pc">, DwarfRegNum<[ 16 ]>;
- def PR : SHRegister<23, "pr">, DwarfRegNum<[ 17 ]>;
-
- // FR Registers
-
- // TODO: Add float registers
+ def PR : SysReg<0, "pr">; // Procedure Register
+ def PC : SysReg<0, "pc">; // Program Counter
+ def MACL : SysReg<0, "macl">; // Mult & Accum Low
+ def MACH : SysReg<1, "mach">; // Mult & Accum Hi
+ def FPSCR : SysReg<0, "fpscr">; // FPU Status/Control Register
+ def FPUL : SysReg<0, "fpul">; // FPU Comms Register
+
+ // 32-bit floating point registers
+ foreach I = 0-15 in
+ def FR#I : FRReg<I, "fr"#I>, DwarfRegNum<[!add(I, 16)]>;
+ foreach I = 0-15 in
+ def XF#I : FRReg<!add(I, 16), "xf"#I>, DwarfRegNum<[!add(I, 32)]>;
+
+ // 64-bit floating point registers
+ foreach I = 0-7 in
+ def DR#I : DRReg<!shl(I, 1), "dr"#!shl(I, 1),
+ [!cast<FPReg>("FR"#!shl(I, 1)),
+ !cast<FPReg>("FR"#!add(!shl(I, 1), 1)]>;
+ foreach I = 0-7 in
+ def XD#I : DRReg<!shl(I, 1), "xd"#!shl(I, 1),
+ [!cast<FPReg>("XF"#!shl(I, 1)),
+ !cast<FPReg>("XF"#!add(!shl(I, 1), 1)]>;
+
+ // 128-bit floating point vector registers
+ foreach I = 0-3 in
+ def FV#I : FVReg<!shl(I, 2), "fv"#!shl(I, 2),
+ [!cast<FPReg>("FR"#!shl(I, 2)),
+ !cast<FPReg>("FR"#!add(!shl(I, 2), 1)),
+ !cast<FPReg>("FR"#!add(!shl(I, 2), 2)),
+ !cast<FPReg>("XF"#!add(!shl(I, 2), 3)]>;
+
+ // 512-bit matrix register (shadows XF registers)
+ // TODO: Add proper subregisters here.
+ def MtrxReg : MTRXReg<0, "xmtrx">;
}
//===----------------------------------------------------------------------===//
// Register Classes
//===----------------------------------------------------------------------===//
-def GPR : RegisterClass<"SH", [i32], 32, (
+def GPR : RegisterClass<"SH", [ i32 ], 32, (
add(
R0, R1, R2, R3, R4, R5, R6, R7, // Banked memory
R8, R9, R10, R11, R12, R13, R14, R15, // Non-banked memory.
)
)>;
-// Control registers
-def CR : RegisterClass<"SH", [i32], 32, (add SR, GBR, VBR>) {
- let CopyCost = -1;
- let isAllocatable = 0;
-}
+// 32-bit floating point registers.
+def FGR32 : RegisterClass<"SH", [f32], 32, (
+ add(
+ // FR
+ FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7,
+ FR8, FR9, FR10, FR11, FR12, FR13, FR14, FR15,
+
+ // XF
+ XF0, XF1, XF2, XF3, XF4, XF5, XF6, XF7,
+ XF8, XF9, XF10, XF11, XF12, XF13, XF14, XF15,
+ )
+)>;
-// System registers.
-def SYSR : RegisterClass<"SH", [ i32 ], 32, (add MACH, MACL, PR, PC)> {
- let CopyCost = -1;
- let isAllocatable = 0;
-}
+// 64-bit floating point registers.
+def FGR64 : RegisterClass<"SH", [f64], 64, (add
+ // DR
+ DR0, DR1, DR2, DR3, DR4, DR5, DR6, DR7,
+ DR8, DR9, DR10, DR11, DR12, DR13, DR14, DR15,
-// MAC register.
-def MACR : RegisterClass<"SH", [ i64 ], 64, (add MAC)> {
- let CopyCost = -1;
- let isAllocatable = 0;
-}
+ // XD
+ XD0, XD1, XD2, XD3, XD4, XD5, XD6, XD7,
+ XD8, XD9, XD10, XD11, XD12, XD13, XD14, XD15,
+)>;
+
+// Vector registers
+def VEC128 : RegisterClass<"SH", [v4f32], 128, (add
+ FV0, FV4, FV8, FV12)>;
+
+// Matrix register
+def MTRX512 : RegisterClass<"SH", [v16f32],
+ (add (sequence "FR%u", 0, 15), (sequence "XF%u", 0, 15))>;
-def PCR : RegisterClass<"SH", [ i32 ], 32, (add PC)> {
- let CopyCost = -1;
- let isAllocatable = 0;
-}
\ No newline at end of file
+// Control registers
+def CR : RegisterClass<"SH", [ i32 ], 32,
+ (add SR, GBR, VBR, SGR, DBR, SSR, SPC)>, Unallocatable;
+
+// System registers.
+def SR : RegisterClass<"SH", [ i32 ], 32,
+ (add PR, PC, MACL, MACH, FPSCR, FPUL)>, Unallocatable;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
index b676f36dc8d55..4045218737a15 100644
--- a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
@@ -18,6 +18,6 @@ Target &llvm::getTheSuperHTarget() {
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeSuperHTargetInfo() {
- RegisterTarget<Triple::superh, /*HasJIT=*/false> X(getTheSuperHTarget(),
+ RegisterTarget<Triple::sh, /*HasJIT=*/false> X(getTheSuperHTarget(),
"sh", "SuperH", "SuperH");
}
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index c6515425b7eb5..593af6c736a70 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -106,6 +106,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
return "riscv32be";
case riscv64be:
return "riscv64be";
+ case sh:
+ return "sh";
case shave:
return "shave";
case sparc:
@@ -1229,6 +1231,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::riscv64:
case Triple::riscv32be:
case Triple::riscv64be:
+ case Triple::sh:
case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
@@ -1992,6 +1995,7 @@ unsigned Triple::getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::renderscript32:
case llvm::Triple::riscv32:
case llvm::Triple::riscv32be:
+ case llvm::Triple::sh:
case llvm::Triple::shave:
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
@@ -2103,6 +2107,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::renderscript32:
case Triple::riscv32:
case Triple::riscv32be:
+ case Triple::sh:
case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
@@ -2195,6 +2200,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::m68k:
case Triple::msp430:
case Triple::r600:
+ case Triple::sh:
case Triple::shave:
case Triple::sparcel:
case Triple::tce:
>From ce4eae98f73971bfbbeff78b7db7cd2d1df67e55 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 31 May 2026 04:20:05 +0200
Subject: [PATCH 04/39] Set up asm parser scaffolding
---
llvm/include/llvm/TargetParser/Triple.h | 3 +-
.../Target/SuperH/AsmParser/CMakeLists.txt | 14 +++
.../SuperH/AsmParser/SuperHAsmParser.cpp | 23 ++++
llvm/lib/Target/SuperH/CMakeLists.txt | 12 +-
.../Target/SuperH/MCTargetDesc/CMakeLists.txt | 4 +-
.../SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 69 ++++++++++
.../SuperH/MCTargetDesc/SuperHInstPrinter.h | 48 +++++++
.../SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp | 25 ++++
.../SuperH/MCTargetDesc/SuperHMCAsmInfo.h | 39 ++++++
.../MCTargetDesc/SuperHMCTargetDesc.cpp | 82 +++++++++++-
.../SuperH/MCTargetDesc/SuperHMCTargetDesc.h | 6 +
llvm/lib/Target/SuperH/SuperH.td | 78 ++++++++++--
llvm/lib/Target/SuperH/SuperHInstrData.td | 13 ++
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 25 +++-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 37 ++++++
llvm/lib/Target/SuperH/SuperHRegisterInfo.td | 118 ++++++++----------
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 27 ++--
llvm/lib/Target/SuperH/SuperHTargetMachine.h | 5 +-
.../SuperH/TargetInfo/SuperHTargetInfo.cpp | 10 +-
.../SuperH/TargetInfo/SuperHTargetInfo.h | 1 +
llvm/lib/TargetParser/TargetDataLayout.cpp | 28 +++++
llvm/lib/TargetParser/Triple.cpp | 13 ++
22 files changed, 581 insertions(+), 99 deletions(-)
create mode 100644 llvm/lib/Target/SuperH/AsmParser/CMakeLists.txt
create mode 100644 llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
create mode 100644 llvm/lib/Target/SuperH/SuperHInstrData.td
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 25b35bb99edb7..375e96c6486f0 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -79,7 +79,8 @@ class Triple {
riscv64, // RISC-V (64-bit, little endian): riscv64
riscv32be, // RISC-V (32-bit, big endian): riscv32be
riscv64be, // RISC-V (64-bit, big endian): riscv64be
- sh, // SuperH: sh
+ sh, // SuperH (big endian): sh
+ sh_le, // SuperH (little endian): sh_le
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
diff --git a/llvm/lib/Target/SuperH/AsmParser/CMakeLists.txt b/llvm/lib/Target/SuperH/AsmParser/CMakeLists.txt
new file mode 100644
index 0000000000000..5f75407e92d4c
--- /dev/null
+++ b/llvm/lib/Target/SuperH/AsmParser/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_llvm_component_library(LLVMSuperHAsmParser
+ SuperHAsmParser.cpp
+
+ LINK_COMPONENTS
+ MC
+ MCParser
+ SuperHDesc
+ SuperHInfo
+ Support
+ TargetParser
+
+ ADD_TO_COMPONENT
+ SuperH
+ )
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
new file mode 100644
index 0000000000000..6ed41223b23eb
--- /dev/null
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -0,0 +1,23 @@
+//===-- SuperHAsmParser.cpp - Parse SH assembly to MCInst instructions ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SuperHMCAsmInfo.h"
+#include "TargetInfo/SuperHTargetInfo.h"
+#include "llvm/MC/MCELFStreamer.h"
+#include "llvm/MC/MCInstrAnalysis.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/TargetRegistry.h"
+#include <sstream>
+
+using namespace llvm;
+
+extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
+LLVMInitializeSuperHAsmParser() { }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index a12dcbc2e101d..64d7df4fb153e 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -2,24 +2,34 @@ add_llvm_component_group(SuperH)
set(LLVM_TARGET_DEFINITIONS SuperH.td)
-# add_public_tablegen_target(SuperHCommonTableGen)
+tablegen(LLVM SuperHGenRegisterInfo.inc -gen-register-info)
+#tablegen(LLVM SuperHGenInstrInfo.inc -gen-instr-info)
+tablegen(LLVM SuperHGenSubtargetInfo.inc -gen-subtarget)
+
+add_public_tablegen_target(SuperHCommonTableGen)
add_llvm_target(SuperHCodeGen
SuperHTargetMachine.cpp
LINK_COMPONENTS
+ Analysis
AsmPrinter
CodeGen
+ CodeGenTypes
Core
MC
SelectionDAG
+ SuperHDesc
+ SuperHInfo
Support
Target
TargetParser
+ TransformUtils
ADD_TO_COMPONENT
SuperH
)
+add_subdirectory(AsmParser)
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
index a9a69ea22dc05..181ec4b281c14 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
@@ -1,9 +1,11 @@
add_llvm_component_library(LLVMSuperHDesc
SuperHMCTargetDesc.cpp
+ SuperHMCAsmInfo.cpp
+ SuperHInstPrinter.cpp
LINK_COMPONENTS
MC
- MCDisassembler
+ SuperHInfo
Support
TargetParser
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
new file mode 100644
index 0000000000000..2b32ae9c389e0
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -0,0 +1,69 @@
+//===-- SuperHMCTargetDesc.cpp - SuperH assembly syntax printer -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// \file
+// This file provides the ability to write SuperH instructions to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHInstPrinter.h"
+// #include "SuperHInstrInfo.h"
+#include "llvm/ADT/StringExtras.h"
+#include <llvm/MC/MCInst.h>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-isel"
+
+#define PRINT_ALIAS_INSTR
+// #include "SuperHGenAsmWriter.inc"
+
+SuperHInstPrinter::SuperHInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI) : MCInstPrinter(MAI, MII, MRI) {}
+
+void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
+ OS << StringRef(getRegisterName(Reg)).lower();
+}
+
+void SuperHInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
+ const MCSubtargetInfo &STI, raw_ostream &OS) {
+ printInstruction(MI, Address, OS);
+}
+
+void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+
+ // Print Register
+ if (Op.isReg()) {
+ printRegName(O, Op.getReg());
+ return;
+ }
+
+ // Print immediates
+ if (Op.isImm()) {
+ assert(Op.getImm() <= 255 && "Only 8-bit immediates are supported.");
+ O << "#" << Op.getImm();
+ return;
+ }
+}
+
+// TODO: Delete this placeholder.
+void SuperHInstPrinter::printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O) {
+
+}
+
+// TODO: Delete this placeholder.
+const char *SuperHInstPrinter::getRegisterName(MCRegister Reg) {
+ return "r";
+}
+
+std::pair<const char *, uint64_t> SuperHInstPrinter::getMnemonic(const MCInst &MI) const {
+ std::pair<const char *, uint64_t> Ret;
+
+ return Ret;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
new file mode 100644
index 0000000000000..d1b26b0e2f93d
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -0,0 +1,48 @@
+//===-- SuperHMCTargetDesc.h - SuperH assembly syntax printer -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// \file
+// This file provides the ability to write SuperH instructions to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHINSTPRINTER_H
+#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHINSTPRINTER_H
+
+#include "llvm/MC/MCInstPrinter.h"
+#include <llvm/MC/MCExpr.h>
+#include <llvm/MC/MCInstrInfo.h>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+//
+// Class which provides the ability to write SuperH instructions to a .s file.
+//
+//===----------------------------------------------------------------------===//
+class SuperHInstPrinter : public MCInstPrinter {
+public:
+ SuperHInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI);
+
+ // Autogenerated by tablegen
+ void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
+ static const char *getRegisterName(MCRegister Reg);
+
+ void printRegName(raw_ostream &OS, MCRegister Reg) override;
+ void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
+ const MCSubtargetInfo &STI, raw_ostream &OS) override;
+ std::pair<const char *, uint64_t> getMnemonic(const MCInst &MI) const override;
+
+private:
+ void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+};
+
+} // end namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
new file mode 100644
index 0000000000000..323bb8e703ed8
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -0,0 +1,25 @@
+//===-- SuperHMCAsmInfo.cpp - SuperH Asm Info -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file provides the SuperHAsmInfo class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "SuperHMCAsmInfo.h"
+#include "llvm/TargetParser/Triple.h"
+
+using namespace llvm;
+
+void SuperHMCAsmInfo::anchor() {}
+
+SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
+ const MCTargetOptions &Options)
+ : MCAsmInfoELF(Options) {
+ this->IsLittleEndian = TheTriple.isLittleEndian();
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
new file mode 100644
index 0000000000000..25cd78f53becc
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
@@ -0,0 +1,39 @@
+//===-- SuperHMCAsmInfo.h - SuperH Asm Info -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file provides the SuperHAsmInfo class.
+///
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCASMINFO_H
+#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCASMINFO_H
+
+#include "llvm/MC/MCAsmInfoELF.h"
+
+namespace llvm {
+class Triple;
+
+//===----------------------------------------------------------------------===//
+//
+// Class which provides the information needed to emit a SuperH ELF file.
+//
+//===----------------------------------------------------------------------===//
+class SuperHMCAsmInfo : public MCAsmInfoELF {
+private:
+ void anchor() override;
+
+public:
+ explicit SuperHMCAsmInfo(const Triple &TheTriple,
+ const MCTargetOptions &Options);
+};
+
+} // end namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
index d7ac60efb4563..4a8a31532c0e4 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
@@ -1,4 +1,5 @@
-//===-- SuperHMCTargetDesc.cpp - SuperH Target Descriptions ---------*- C++ -*-===//
+//===-- SuperHMCTargetDesc.cpp - SuperH Target Descriptions ---------*- C++
+//-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -12,6 +13,8 @@
//===----------------------------------------------------------------------===//
#include "SuperHMCTargetDesc.h"
+#include "SuperHInstPrinter.h"
+#include "SuperHMCAsmInfo.h"
#include "TargetInfo/SuperHTargetInfo.h"
#include "llvm/MC/MCELFStreamer.h"
@@ -28,7 +31,80 @@
using namespace llvm;
-extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY
-void LLVMInitializeSuperHTargetMC() {
+#define GET_REGINFO_MC_DESC
+#include "SuperHGenRegisterInfo.inc"
+#define GET_SUBTARGETINFO_MC_DESC
+#include "SuperHGenSubtargetInfo.inc"
+
+static MCInstrInfo *createSuperHMCInstrInfo() {
+ MCInstrInfo *X = new MCInstrInfo();
+ // InitSuperHMCInstrInfo(X);
+ return X;
+}
+
+static MCRegisterInfo *createSuperHMCRegisterInfo(const Triple &TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ // InitSuperHRegisterInfo(X);
+ return X;
+}
+
+static MCSubtargetInfo *
+createSuperHMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
+ return createSuperHMCSubtargetInfoImpl(TT, CPU, CPU, FS);
+}
+
+static MCInstPrinter *createSuperHMCInstPrinter(const Triple &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI) {
+ return new SuperHInstPrinter(MAI, MII, MRI);
+}
+
+static MCAsmInfo *createSuperHMCAsmInfo(const MCRegisterInfo &MRI,
+ const Triple &TT,
+ const MCTargetOptions &Options) {
+ MCAsmInfo *MAI = new SuperHMCAsmInfo(TT, Options);
+ return MAI;
+}
+
+extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
+LLVMInitializeSuperHTargetMC() {
+
+ // SuperH (big-endian)
+ for (Target *T : {&getTheSuperHTarget()}) {
+ // Register the MC asm info.
+ TargetRegistry::RegisterMCAsmInfo(*T, createSuperHMCAsmInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(*T, createSuperHMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(*T, createSuperHMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(*T, createSuperHMCSubtargetInfo);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(*T, createSuperHMCInstPrinter);
+ }
+
+ // SuperH (little-endian)
+ for (Target *T : {&getTheSuperHLETarget()}) {
+ // Register the MC asm info.
+ TargetRegistry::RegisterMCAsmInfo(*T, createSuperHMCAsmInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(*T, createSuperHMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(*T, createSuperHMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(*T, createSuperHMCSubtargetInfo);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(*T, createSuperHMCInstPrinter);
+ }
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
index b1428a0b33366..6bb8d438df3ff 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
@@ -18,6 +18,12 @@
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/Support/DataTypes.h"
+#define GET_REGINFO_ENUM
+#include "SuperHGenRegisterInfo.inc"
+
+#define GET_SUBTARGETINFO_ENUM
+#include "SuperHGenSubtargetInfo.inc"
+
namespace llvm {
class MCAsmBackend;
class MCCodeEmitter;
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index cd7ef7e54f403..8ec78f923ee4e 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -20,24 +20,48 @@ include "llvm/Target/Target.td"
// SuperH Subtarget features
//===----------------------------------------------------------------------===//
-def FeatureFPU : SubtargetFeature<"fpu", "HasFPU", "false",
- "Enable FPU Support">;
-def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU", "true",
- "Enable vector FPU instructions">;
+// NOTE: Some SH4 CPUs support FSCA and FSRRA despite their
+// ISA manuals not specifying so.
+def FeatureFSCA : SubtargetFeature<"fsca", "HasFSCA", "true",
+ "Enable use of fsca instruction.">;
+def FeatureFSRRA : SubtargetFeature<"fsrra", "HasFSRRA", "true",
+ "Enable use of fsrra instruction.">;
+def FeatureFP32 : SubtargetFeature<"fp32", "HasFP32", "true",
+ "Enable use of 32-bit floating point instructions.">;
+def FeatureFP64 : SubtargetFeature<"fp64", "HasFP64", "true",
+ "Enable use of 64-bit floating point instructions.">;
+def FeatureDSP : SubtargetFeature<"dsp", "HasDSP", "true",
+ "Enable SuperH DSP Extensions">;
+
+//===----------------------------------------------------------------------===//
+// SuperH CPU Family features
+//===----------------------------------------------------------------------===//
+
def FeatureSH1 : SubtargetFeature<"sh1", "SHArchVersion", "SH1",
"SH-1 ISA Support">;
def FeatureSH2 : SubtargetFeature<"sh2", "SHArchVersion", "SH2",
"SH-2 ISA Support",
[FeatureSH1]>;
+def FeatureSH2E : SubtargetFeature<"sh2e", "SHArchVersion", "SH2E",
+ "SH-2E ISA Support",
+ [FeatureSH1, FeatureSH2, FeatureFP32]>;
+def FeatureSH2A : SubtargetFeature<"sh2a", "SHArchVersion", "SH2A",
+ "SH-2A ISA Support",
+ [FeatureSH1, FeatureSH2, FeatureFP32, FeatureFP64]>;
def FeatureSH3 : SubtargetFeature<"sh3", "SHArchVersion", "SH3",
"SH-3 ISA Support",
[FeatureSH1, FeatureSH2]>;
-def FeatureSH4 : SubtargetFeature<"sh4", "SHArchVersion", "SH3",
+def FeatureSH3E : SubtargetFeature<"sh3e", "SHArchVersion", "SH3E",
+ "SH-3E ISA Support",
+ [FeatureSH1, FeatureSH2, FeatureFP32]>;
+def FeatureSH4 : SubtargetFeature<"sh4", "SHArchVersion", "SH4",
"SH-4 ISA Support",
- [FeatureSH1, FeatureSH2, FeatureSH3, FeatureFPU]>;
+ [FeatureSH1, FeatureSH2, FeatureSH3, FeatureFP32,
+ FeatureFP64]>;
def FeatureSH4A : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
"SH-4A ISA Support",
- [FeatureSH1, FeatureSH2, FeatureSH3, FeatureSH4, FeatureFPU]>;
+ [FeatureSH1, FeatureSH2, FeatureSH3, FeatureSH4,
+ FeatureFP32, FeatureFP64, FeatureFSCA, FeatureFSRRA]>;
//===----------------------------------------------------------------------===//
// SuperH Processors
@@ -46,7 +70,7 @@ def FeatureSH4A : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
include "SuperHSchedule.td"
class Proc<string Name, list<SubtargetFeature> Features>
- : ProcessorModel<Name, GenericSHModel, Features>;
+ : ProcessorModel<Name, GenericSuperHModel, Features>;
def : Proc<"generic", [FeatureSH4]>;
def : Proc<"sh1", [FeatureSH1]>;
@@ -55,6 +79,12 @@ def : Proc<"sh3", [FeatureSH3]>;
def : Proc<"sh4", [FeatureSH4]>;
def : Proc<"sh4a", [FeatureSH4A]>;
+// NOTE: SEGA got some special variants of the SuperH family
+// produced with some extra features enabled, defining them here.
+def : Proc<"dreamcast", [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
+def : Proc<"naomi", [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
+def : Proc<"saturn", [FeatureSH2]>;
+
//===----------------------------------------------------------------------===//
// Register File Description
//===----------------------------------------------------------------------===//
@@ -65,14 +95,42 @@ include "SuperHRegisterInfo.td"
// Instruction Descriptions
//===----------------------------------------------------------------------===//
-// include "SuperHInstrInfo.td"
-
+include "SuperHInstrInfo.td"
def SuperHInstrInfo : InstrInfo;
+//===----------------------------------------------------------------------===//
+// Calling Conventions
+//===----------------------------------------------------------------------===//
+
+
+//===---------------------------------------------------------------------===//
+// Assembly Printers
+//===---------------------------------------------------------------------===//
+
+def SuperHAsmWriter : AsmWriter {
+ string AsmWriterClassName = "InstPrinter";
+ bit isMCAsmWriter = 1;
+}
+
+//===---------------------------------------------------------------------===//
+// Assembly Parsers
+//===---------------------------------------------------------------------===//
+
+def SuperHAsmParser : AsmParser {
+ let ShouldEmitMatchRegisterName = 0;
+ let ShouldEmitMatchRegisterAltName = 0;
+}
+
+def SuperHAsmParserVariant : AsmParserVariant {
+ int Variant = 0;
+}
+
//===----------------------------------------------------------------------===//
// Target Declaration
//===----------------------------------------------------------------------===//
def SuperH : Target {
let InstructionSet = SuperHInstrInfo;
+ let AssemblyParsers = [SuperHAsmParser];
+ let AssemblyWriters = [SuperHAsmWriter];
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrData.td b/llvm/lib/Target/SuperH/SuperHInstrData.td
new file mode 100644
index 0000000000000..d272437fff6b0
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrData.td
@@ -0,0 +1,13 @@
+//===-- SuperHInstrData.td - SuperH Data Transfer Instructions -*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes all of the data transfer instructions in the SuperH
+/// ISA.
+///
+//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index d3bacb075c9ba..de042add3c8c8 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -9,13 +9,32 @@
class SHInst<dag outs, dag ins, string asmstr, list<dag> pattern>
: Instruction {
- let Namespace = "SH";
+ let Namespace = "SH";
dag OutOperandList = outs;
dag InOperandList = ins;
- let AsmString = asmtr;
+ let AsmString = asmstr;
let Pattern = pattern;
field bits<16> Inst;
+ let Size = 1;
+}
+
+class SHDSPInst<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : Instruction {
+
+ let Namespace = "SH";
+ dag OutOperandList = outs;
+ dag InOperandList = ins;
+ let AsmString = asmstr;
+ let Pattern = pattern;
+
+ field bits<32> Inst;
let Size = 2;
-}
\ No newline at end of file
+}
+
+// SH PSEUDO INSTRUCTION
+class SHPseudo<dag outs, dag ins, list<dag> pattern = []>
+ : SHInst<outs, ins, "; error: this should not be emitted", pattern> {
+ let isPseudo = 1;
+}
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index a4451d7a502d5..f085dd1ec52bc 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -11,6 +11,11 @@
/// and properties of the instructions which are needed for code generation,
/// machine code emission, and analysis.
///
+/// The subsystems are ordered after the instruction classification that
+/// The SuperH ISA manuals use.
+///
+/// See: https://www.shared-ptr.com/sh_insns.html
+///
//===----------------------------------------------------------------------===//
include "SuperHInstrFormats.td"
@@ -19,3 +24,35 @@ include "SuperHInstrFormats.td"
// SuperH Type Profiles
//===----------------------------------------------------------------------===//
+def SHSDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+def SHSDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+def SHSDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
+def SHSDT_Ret : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
+
+//===----------------------------------------------------------------------===//
+// Nodes
+//===----------------------------------------------------------------------===//
+
+def SHCallSeqStart : SDNode<"ISD::CALLSEQ_START", SHSDT_CallSeqStart,
+ [SDNPHasChain, SDNPOutGlue]>;
+
+def SHCallSeqEnd : SDNode<"ISD::CALLSEQ_END", SHSDT_CallSeqEnd,
+ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+
+def SHCall : SDNode<"SHISD::CALL", SHSDT_Call,
+ [SDNPHasChain, SDNPOutGlue,
+ SDNPOptInGlue, SDNPVariadic]>;
+
+def SHRet : SDNode<"SHISD::RET", SHSDT_Ret,
+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
+
+//===----------------------------------------------------------------------===//
+// Operands
+//===----------------------------------------------------------------------===//
+
+
+//===----------------------------------------------------------------------===//
+// Subsystems
+//===----------------------------------------------------------------------===//
+
+include "SuperHInstrData.td"
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index abf4cbfcc3ba2..d8767915dfb45 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -49,13 +49,13 @@ class SHRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs>
}
// SH General Purpose Registers.
-class GPRReg<bits<16> Enc, string n> : MipsReg<Enc, n>;
+class GPRReg<bits<16> Enc, string n> : SHReg<Enc, n>;
// Control Registers
-class CtrlReg<bits<16> Enc, string n> : MipsReg<Enc, n>;
+class CtrlReg<bits<16> Enc, string n> : SHReg<Enc, n>;
// SH System Registers.
-class SysReg<bits<16> Enc, string n> : MipsReg<Enc, n>;
+class SysReg<bits<16> Enc, string n> : SHReg<Enc, n>;
// 32-bit floating point registers
class FRReg<bits<16> Enc, string n> : SHReg<Enc, n>;
@@ -84,26 +84,26 @@ class MTRXReg<bits<16> Enc, string n> : SHReg<Enc, n>;
let Namespace = "SH" in {
// General Purpose Registers
- def R0 : SHGPRReg<0, "r0">, DwarfRegNum<[0]>;
- def R1 : SHGPRReg<1, "r1">, DwarfRegNum<[1]>;
- def R2 : SHGPRReg<2, "r2">, DwarfRegNum<[2]>;
- def R3 : SHGPRReg<3, "r3">, DwarfRegNum<[3]>;
- def R4 : SHGPRReg<4, "r4">, DwarfRegNum<[4]>;
- def R5 : SHGPRReg<5, "r5">, DwarfRegNum<[5]>;
- def R6 : SHGPRReg<6, "r6">, DwarfRegNum<[6]>;
- def R7 : SHGPRReg<7, "r7">, DwarfRegNum<[7]>;
- def R8 : SHGPRReg<8, "r8">, DwarfRegNum<[8]>;
- def R9 : SHGPRReg<9, "r9">, DwarfRegNum<[9]>;
- def R10 : SHGPRReg<10, "r10">, DwarfRegNum<[10]>;
- def R11 : SHGPRReg<11, "r11">, DwarfRegNum<[11]>;
- def R12 : SHGPRReg<12, "r12">, DwarfRegNum<[12]>;
- def R13 : SHGPRReg<13, "r13">, DwarfRegNum<[13]>;
- def R14 : SHGPRReg<14, "r14">, DwarfRegNum<[14]>;
- def R15 : SHGPRReg<15, "r15">, DwarfRegNum<[15]>;
+ def R0 : GPRReg<0, "r0">, DwarfRegNum<[0]>;
+ def R1 : GPRReg<1, "r1">, DwarfRegNum<[1]>;
+ def R2 : GPRReg<2, "r2">, DwarfRegNum<[2]>;
+ def R3 : GPRReg<3, "r3">, DwarfRegNum<[3]>;
+ def R4 : GPRReg<4, "r4">, DwarfRegNum<[4]>;
+ def R5 : GPRReg<5, "r5">, DwarfRegNum<[5]>;
+ def R6 : GPRReg<6, "r6">, DwarfRegNum<[6]>;
+ def R7 : GPRReg<7, "r7">, DwarfRegNum<[7]>;
+ def R8 : GPRReg<8, "r8">, DwarfRegNum<[8]>;
+ def R9 : GPRReg<9, "r9">, DwarfRegNum<[9]>;
+ def R10 : GPRReg<10, "r10">, DwarfRegNum<[10]>;
+ def R11 : GPRReg<11, "r11">, DwarfRegNum<[11]>;
+ def R12 : GPRReg<12, "r12">, DwarfRegNum<[12]>;
+ def R13 : GPRReg<13, "r13">, DwarfRegNum<[13]>;
+ def R14 : GPRReg<14, "r14">, DwarfRegNum<[14]>;
+ def R15 : GPRReg<15, "r15">, DwarfRegNum<[15]>;
// Control Registers
- def SR : CtrlReg<0, "sr">; // Status Register
- def GBR : CtrlReg<0, "gbr"; // Global Base Register
+ def SR : CtrlReg<0, "sr">; // Status Register
+ def GBR : CtrlReg<0, "gbr">; // Global Base Register
def VBR : CtrlReg<0, "vbr">; // Vector Base Register
def SGR : CtrlReg<0, "sgr">; // Saved General Register
def DBR : CtrlReg<0, "dbr">; // Debug Base Register
@@ -111,12 +111,12 @@ let Namespace = "SH" in {
def SPC : CtrlReg<0, "spc">; // Saved Program Counter
// System Registers
- def PR : SysReg<0, "pr">; // Procedure Register
- def PC : SysReg<0, "pc">; // Program Counter
- def MACL : SysReg<0, "macl">; // Mult & Accum Low
- def MACH : SysReg<1, "mach">; // Mult & Accum Hi
+ def PR : SysReg<0, "pr">; // Procedure Register
+ def PC : SysReg<0, "pc">; // Program Counter
+ def MACL : SysReg<0, "macl">; // Mult & Accum Low
+ def MACH : SysReg<1, "mach">; // Mult & Accum Hi
def FPSCR : SysReg<0, "fpscr">; // FPU Status/Control Register
- def FPUL : SysReg<0, "fpul">; // FPU Comms Register
+ def FPUL : SysReg<0, "fpul">; // FPU Comms Register
// 32-bit floating point registers
foreach I = 0-15 in
@@ -126,21 +126,21 @@ let Namespace = "SH" in {
// 64-bit floating point registers
foreach I = 0-7 in
- def DR#I : DRReg<!shl(I, 1), "dr"#!shl(I, 1),
- [!cast<FPReg>("FR"#!shl(I, 1)),
- !cast<FPReg>("FR"#!add(!shl(I, 1), 1)]>;
+ def DR#!shl(I, 1) : DRReg<!shl(I, 1), "dr"#!shl(I, 1),
+ [!cast<FRReg>("FR"#!shl(I, 1)),
+ !cast<FRReg>("FR"#!add(!shl(I, 1), 1))]>;
foreach I = 0-7 in
- def XD#I : DRReg<!shl(I, 1), "xd"#!shl(I, 1),
- [!cast<FPReg>("XF"#!shl(I, 1)),
- !cast<FPReg>("XF"#!add(!shl(I, 1), 1)]>;
+ def XD#!shl(I, 1) : DRReg<!shl(I, 1), "xd"#!shl(I, 1),
+ [!cast<FRReg>("XF"#!shl(I, 1)),
+ !cast<FRReg>("XF"#!add(!shl(I, 1), 1))]>;
// 128-bit floating point vector registers
foreach I = 0-3 in
- def FV#I : FVReg<!shl(I, 2), "fv"#!shl(I, 2),
- [!cast<FPReg>("FR"#!shl(I, 2)),
- !cast<FPReg>("FR"#!add(!shl(I, 2), 1)),
- !cast<FPReg>("FR"#!add(!shl(I, 2), 2)),
- !cast<FPReg>("XF"#!add(!shl(I, 2), 3)]>;
+ def FV#!shl(I, 2) : FVReg<!shl(I, 2), "fv"#!shl(I, 2),
+ [!cast<FRReg>("FR"#!shl(I, 2)),
+ !cast<FRReg>("FR"#!add(!shl(I, 2), 1)),
+ !cast<FRReg>("FR"#!add(!shl(I, 2), 2)),
+ !cast<FRReg>("XF"#!add(!shl(I, 2), 3))]>;
// 512-bit matrix register (shadows XF registers)
// TODO: Add proper subregisters here.
@@ -151,49 +151,41 @@ let Namespace = "SH" in {
// Register Classes
//===----------------------------------------------------------------------===//
-def GPR : RegisterClass<"SH", [ i32 ], 32, (
- add(
- R0, R1, R2, R3, R4, R5, R6, R7, // Banked memory
- R8, R9, R10, R11, R12, R13, R14, R15, // Non-banked memory.
- )
+def GPR : RegisterClass<"SH", [ i32 ], 32, (add
+ R0, R1, R2, R3, R4, R5, R6, R7, // Banked memory
+ R8, R9, R10, R11, R12, R13, R14, R15 // Non-banked memory.
)>;
// 32-bit floating point registers.
-def FGR32 : RegisterClass<"SH", [f32], 32, (
- add(
- // FR
- FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7,
- FR8, FR9, FR10, FR11, FR12, FR13, FR14, FR15,
-
- // XF
- XF0, XF1, XF2, XF3, XF4, XF5, XF6, XF7,
- XF8, XF9, XF10, XF11, XF12, XF13, XF14, XF15,
- )
+def FR32 : RegisterClass<"SH", [f32], 32, (add
+ // FR
+ FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7,
+ FR8, FR9, FR10, FR11, FR12, FR13, FR14, FR15,
+
+ // XF
+ XF0, XF1, XF2, XF3, XF4, XF5, XF6, XF7,
+ XF8, XF9, XF10, XF11, XF12, XF13, XF14, XF15
)>;
// 64-bit floating point registers.
-def FGR64 : RegisterClass<"SH", [f64], 64, (add
+def FR64 : RegisterClass<"SH", [f64], 64, (add
// DR
- DR0, DR1, DR2, DR3, DR4, DR5, DR6, DR7,
- DR8, DR9, DR10, DR11, DR12, DR13, DR14, DR15,
+ DR0, DR2, DR4, DR6, DR8, DR10, DR12, DR14,
// XD
- XD0, XD1, XD2, XD3, XD4, XD5, XD6, XD7,
- XD8, XD9, XD10, XD11, XD12, XD13, XD14, XD15,
+ XD0, XD2, XD4, XD6, XD8, XD10, XD12, XD14
)>;
// Vector registers
-def VEC128 : RegisterClass<"SH", [v4f32], 128, (add
- FV0, FV4, FV8, FV12)>;
+def VEC128 : RegisterClass<"SH", [v4f32], 128, (add FV0, FV4, FV8, FV12)>;
// Matrix register
-def MTRX512 : RegisterClass<"SH", [v16f32],
- (add (sequence "FR%u", 0, 15), (sequence "XF%u", 0, 15))>;
+def MTRX512 : RegisterClass<"SH", [v16f32], 512, (add (sequence "FR%u", 0, 15), (sequence "XF%u", 0, 15))>;
// Control registers
-def CR : RegisterClass<"SH", [ i32 ], 32,
+def CTRL : RegisterClass<"SH", [ i32 ], 32,
(add SR, GBR, VBR, SGR, DBR, SSR, SPC)>, Unallocatable;
// System registers.
-def SR : RegisterClass<"SH", [ i32 ], 32,
+def SYS : RegisterClass<"SH", [ i32 ], 32,
(add PR, PC, MACL, MACH, FPSCR, FPUL)>, Unallocatable;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 91673573b22b2..7001640d4dc15 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -1,4 +1,5 @@
-//===-- SuperHTargetMachine.cpp - Define TargetMachine for SuperH -----------===//
+//===-- SuperHTargetMachine.cpp - Define TargetMachine for SuperH
+//-----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -20,21 +21,23 @@
using namespace llvm;
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSuperHTarget() {
- RegisterTargetMachine<SuperHTargetMachine> SH(getTheSuperHTarget());
+ RegisterTargetMachine<SuperHTargetMachine> SH(getTheSuperHTarget());
+ RegisterTargetMachine<SuperHTargetMachine> SHLE(getTheSuperHLETarget());
}
-SuperHTargetMachine::~SuperHTargetMachine() { }
+SuperHTargetMachine::~SuperHTargetMachine() {}
/// Create a SuperH architecture model.
SuperHTargetMachine::SuperHTargetMachine(const Target &T, const Triple &TT,
- StringRef CPU, StringRef FS,
- const TargetOptions &Options,
- std::optional<Reloc::Model> RM,
- std::optional<CodeModel::Model> CM,
- CodeGenOptLevel OL, bool JIT)
- : CodeGenTargetMachineImpl(
- T, TT.computeDataLayout(), TT, CPU, FS, Options,
- RM.value_or(Reloc::Static), getEffectiveCodeModel(CM, CodeModel::Small),
- OL) {
+ StringRef CPU, StringRef FS,
+ const TargetOptions &Options,
+ std::optional<Reloc::Model> RM,
+ std::optional<CodeModel::Model> CM,
+ CodeGenOptLevel OL, bool JIT)
+ : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,
+ RM.value_or(Reloc::Static),
+ getEffectiveCodeModel(CM, CodeModel::Small),
+ OL) {
+ initAsmInfo();
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.h b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
index 5da814b766f4a..2b090d24ac13f 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.h
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
@@ -20,10 +20,6 @@
namespace llvm {
class SuperHTargetMachine : public CodeGenTargetMachineImpl {
-private:
-
-protected:
-
public:
SuperHTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
@@ -33,6 +29,7 @@ class SuperHTargetMachine : public CodeGenTargetMachineImpl {
~SuperHTargetMachine() override;
};
+
} // end namespace llvm
#endif
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
index 4045218737a15..83c5970fc6783 100644
--- a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
@@ -9,6 +9,7 @@
#include "TargetInfo/SuperHTargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Compiler.h"
+
using namespace llvm;
Target &llvm::getTheSuperHTarget() {
@@ -16,8 +17,15 @@ Target &llvm::getTheSuperHTarget() {
return TheSuperHTarget;
}
+Target &llvm::getTheSuperHLETarget() {
+ static Target TheSuperHLETarget;
+ return TheSuperHLETarget;
+}
+
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeSuperHTargetInfo() {
RegisterTarget<Triple::sh, /*HasJIT=*/false> X(getTheSuperHTarget(),
- "sh", "SuperH", "SuperH");
+ "sh", "SuperH (big endian)", "SuperH");
+ RegisterTarget<Triple::sh_le, /*HasJIT=*/false> Y(getTheSuperHLETarget(),
+ "sh_le", "SuperH (little endian)", "SuperH");
}
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.h b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.h
index 38b501e05d46e..9dbef1aa07841 100644
--- a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.h
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.h
@@ -14,6 +14,7 @@ namespace llvm {
class Target;
Target &getTheSuperHTarget();
+Target &getTheSuperHLETarget();
} // namespace llvm
diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp
index a2125eeb82932..d0a5ae9544b7e 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -552,6 +552,31 @@ static std::string computeVEDataLayout(const Triple &T) {
return Ret;
}
+static std::string computeSuperHDataLayout(const Triple &T) {
+
+ // Mixed-endian
+ std::string Ret = T.getArch() == Triple::sh_le ? "e" : "E";
+
+ // ELF name manging
+ Ret += "-m:e";
+
+ // 32-bit pointers, 32 bit aligned
+ Ret += "-p:32:32";
+
+ // 32 bit integers, 32 bit aligned
+ Ret += "-i32:32";
+
+ // 32 bit alignment of objects of aggregate type
+ Ret += "-a:0:32";
+
+ // 32 bit native integer width
+ Ret += "-n32";
+
+ // 32 bit natural stack alignment
+ Ret += "-S32";
+ return Ret;
+}
+
std::string Triple::computeDataLayout(StringRef ABIName) const {
switch (getArch()) {
case Triple::arm:
@@ -611,6 +636,9 @@ std::string Triple::computeDataLayout(StringRef ABIName) const {
return computeSparcDataLayout(*this);
case Triple::systemz:
return computeSystemZDataLayout(*this);
+ case Triple::sh:
+ case Triple::sh_le:
+ return computeSuperHDataLayout(*this);
case Triple::tce:
return "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:32-"
"f16:16:16-f32:32:32-f64:32:32-v64:64:64-i128:128-v128:128:128-"
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 593af6c736a70..1e9d675ff5162 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -108,6 +108,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
return "riscv64be";
case sh:
return "sh";
+ case sh_le:
+ return "sh_le";
case shave:
return "shave";
case sparc:
@@ -1232,6 +1234,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::riscv32be:
case Triple::riscv64be:
case Triple::sh:
+ case Triple::sh_le:
case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
@@ -1996,6 +1999,7 @@ unsigned Triple::getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::riscv32:
case llvm::Triple::riscv32be:
case llvm::Triple::sh:
+ case llvm::Triple::sh_le:
case llvm::Triple::shave:
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
@@ -2108,6 +2112,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::riscv32:
case Triple::riscv32be:
case Triple::sh:
+ case Triple::sh_le:
case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
@@ -2201,6 +2206,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::msp430:
case Triple::r600:
case Triple::sh:
+ case Triple::sh_le:
case Triple::shave:
case Triple::sparcel:
case Triple::tce:
@@ -2381,6 +2387,9 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::sparcel:
T.setArch(Triple::sparc);
break;
+ case Triple::sh_le:
+ T.setArch(Triple::sh);
+ break;
case Triple::tcele:
T.setArch(Triple::tce);
break;
@@ -2436,6 +2445,9 @@ Triple Triple::getLittleEndianArchVariant() const {
case Triple::sparc:
T.setArch(Triple::sparcel);
break;
+ case Triple::sh:
+ T.setArch(Triple::sh_le);
+ break;
case Triple::tce:
T.setArch(Triple::tcele);
break;
@@ -2476,6 +2488,7 @@ bool Triple::isLittleEndian() const {
case Triple::riscv32:
case Triple::riscv64:
case Triple::shave:
+ case Triple::sh_le:
case Triple::sparcel:
case Triple::spir64:
case Triple::spir:
>From ef94ab52dbd725ceca140a7a92e42265d066647e Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 3 Jun 2026 07:14:07 +0200
Subject: [PATCH 05/39] Add SuperH ELF reloc info
---
llvm/include/llvm/BinaryFormat/ELF.h | 5 +++
.../llvm/BinaryFormat/ELFRelocs/SuperH.def | 38 +++++++++++++++++++
2 files changed, 43 insertions(+)
create mode 100644 llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 72cded68463a6..6bc9e2a6168d2 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -727,6 +727,11 @@ enum {
#undef ELF_RISCV_NONSTANDARD_RELOC
};
+// ELF Relocation types for SuperH
+enum {
+#include "ELFRelocs/SuperH.def"
+};
+
enum {
// Symbol may follow different calling convention than the standard calling
// convention.
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
new file mode 100644
index 0000000000000..031ecbc6a6448
--- /dev/null
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
@@ -0,0 +1,38 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// IDs are taken from the Renesas C ABI Specification.
+// See: https://www.renesas.com/en/document/mat/superh-cc-compiler-package-v904-users-manual?r=1169516
+
+ELF_RELOC(R_SH_NONE, 0)
+ELF_RELOC(R_SH_GOT32, 160)
+ELF_RELOC(R_SH_GOT_LOW16, 169)
+ELF_RELOC(R_SH_GOT_MEDLOW16, 170)
+ELF_RELOC(R_SH_GOT_MEDHI16, 171)
+ELF_RELOC(R_SH_GOT_HI16, 172)
+ELF_RELOC(R_SH_GOT10BY4, 189)
+ELF_RELOC(R_SH_GOT10BY8, 191)
+ELF_RELOC(R_SH_PLT32, 161)
+ELF_RELOC(R_SH_PLT_LOW16, 177)
+ELF_RELOC(R_SH_PLT_MEWLOW16, 178)
+ELF_RELOC(R_SH_PLT_MEDHI16, 179)
+ELF_RELOC(R_SH_PLT_HI16, 180)
+ELF_RELOC(R_SH_GOTPLT32, 168)
+ELF_RELOC(R_SH_GOTPLT_LOW16, 169)
+ELF_RELOC(R_SH_GOTPLT_MEDLOW16, 170)
+ELF_RELOC(R_SH_GOTPLT_MEDHI16, 171)
+ELF_RELOC(R_SH_GOTPLT_HI16, 172)
+ELF_RELOC(R_SH_GOTPLT10BY4, 189)
+ELF_RELOC(R_SH_GOTPLT10BY8, 191)
+ELF_RELOC(R_SH_GOTOFF, 166)
+ELF_RELOC(R_SH_GOTOFF_LOW16, 181)
+ELF_RELOC(R_SH_GOTOFF_MEWLOW16, 182)
+ELF_RELOC(R_SH_GOTOFF_MEDHI16, 183)
+ELF_RELOC(R_SH_GOTOFF_HI16, 184)
+ELF_RELOC(R_SH_GOTPC, 167)
+ELF_RELOC(R_SH_GOTPC_LOW16, 185)
+ELF_RELOC(R_SH_GOTPC_MEDLOW16, 186)
+ELF_RELOC(R_SH_GOTPC_MEDHI16, 187)
+ELF_RELOC(R_SH_GOTPC_HI16, 188)
\ No newline at end of file
>From c266c8b01521a3994efcb7df862ae9fb6ae2a116 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 3 Jun 2026 07:15:18 +0200
Subject: [PATCH 06/39] Implement assembler groundwork
---
.../SuperH/AsmParser/SuperHAsmParser.cpp | 418 +++++++++++++++++-
llvm/lib/Target/SuperH/CMakeLists.txt | 22 +-
.../Target/SuperH/MCTargetDesc/CMakeLists.txt | 2 +
.../SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 80 ++++
.../MCTargetDesc/SuperHELFObjectWriter.cpp | 55 +++
.../SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 39 +-
.../SuperH/MCTargetDesc/SuperHInstPrinter.h | 12 +-
.../SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp | 1 +
.../MCTargetDesc/SuperHMCTargetDesc.cpp | 34 +-
.../SuperH/MCTargetDesc/SuperHMCTargetDesc.h | 22 +-
llvm/lib/Target/SuperH/SuperH.h | 19 +
llvm/lib/Target/SuperH/SuperH.td | 35 +-
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 44 ++
llvm/lib/Target/SuperH/SuperHFrameLowering.h | 50 +++
llvm/lib/Target/SuperH/SuperHInstrData.td | 43 ++
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 205 ++++++++-
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 35 ++
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 35 ++
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 56 ++-
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 78 ++++
llvm/lib/Target/SuperH/SuperHRegisterInfo.h | 53 +++
llvm/lib/Target/SuperH/SuperHRegisterInfo.td | 4 +-
llvm/lib/Target/SuperH/SuperHSubtarget.cpp | 22 +
llvm/lib/Target/SuperH/SuperHSubtarget.h | 49 ++
24 files changed, 1320 insertions(+), 93 deletions(-)
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperH.h
create mode 100644 llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHFrameLowering.h
create mode 100644 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHInstrInfo.h
create mode 100644 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHRegisterInfo.h
create mode 100644 llvm/lib/Target/SuperH/SuperHSubtarget.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHSubtarget.h
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 6ed41223b23eb..722c81cbcd0ea 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -7,17 +7,433 @@
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/SuperHMCAsmInfo.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "SuperHRegisterInfo.h"
#include "TargetInfo/SuperHTargetInfo.h"
+#include "llvm/Analysis/Utils/TrainingLogger.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegister.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/MC/MCAsmMacro.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/AsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/raw_ostream.h"
+#include "iostream"
#include <sstream>
+#include <system_error>
using namespace llvm;
+// The generated AsmMatcher SparcGenAsmMatcher uses "SuperH" as the target
+// namespace. But SPARC backend uses "SH" as its namespace.
+namespace llvm {
+namespace SuperH {
+
+ using namespace SH;
+
+} // end namespace SuperH
+} // end namespace llvm
+
+namespace {
+class SuperHOperand;
+
+class SuperHAsmParser : public MCTargetAsmParser {
+ MCAsmParser &Parser;
+ const MCRegisterInfo &MRI;
+
+#define GET_ASSEMBLER_HEADER
+#include "SuperHGenAsmMatcher.inc"
+
+ bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
+ ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
+ MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
+ bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override;
+ ParseStatus parseDirective(AsmToken DirectiveID) override;
+ bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ OperandVector &Operands, MCStreamer &Out,
+ uint64_t &ErrorInfo,
+ bool MatchingInlineAsm) override;
+ ParseStatus parseOperand(OperandVector &Operands);
+ ParseStatus parseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc);
+ ParseStatus parseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc);
+
+public:
+ SuperHAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII)
+ : MCTargetAsmParser(sti, MII), Parser(parser),
+ MRI(*Parser.getContext().getRegisterInfo()) {
+
+ setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
+ }
+};
+
+} // end anonymous namespace
+
+namespace {
+
+class SuperHOperand : public MCParsedAsmOperand {
+public:
+ enum RegisterKind {
+ rk_None,
+ rk_GPR,
+ rk_FR32,
+ rk_FR64,
+ rk_VEC128,
+ rk_XMTRX
+ };
+
+private:
+ enum KindTy {
+ k_Token,
+ k_Register,
+ k_Immediate,
+ } Kind;
+
+ SMLoc StartLoc, EndLoc;
+
+ struct Token {
+ const char *Data;
+ unsigned Length;
+ };
+
+ struct RegOp {
+ MCRegister Reg;
+ RegisterKind Kind;
+ };
+
+ struct ImmOp {
+ const MCExpr *Val;
+ };
+
+ struct MemOp {
+ MCRegister Base;
+ MCRegister OffsetReg;
+ const MCExpr *Off;
+ };
+
+ union {
+ struct Token Tok;
+ struct RegOp Reg;
+ struct ImmOp Imm;
+ struct MemOp Mem;
+ unsigned ASI;
+ unsigned Prefetch;
+ };
+
+public:
+ SuperHOperand(KindTy K) : Kind(K) {}
+
+ bool isToken() const override { return Kind == k_Token; }
+ bool isImm() const override { return Kind == k_Immediate; }
+ bool isReg() const override { return Kind == k_Register; }
+ bool isMem() const override { return false; }
+ bool isImm8() const { return Kind == k_Immediate; }
+
+ SMLoc getStartLoc() const override { return StartLoc; }
+ SMLoc getEndLoc() const override { return EndLoc; }
+
+ 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!");
+ const MCExpr *Expr = getImm();
+ addExpr(Inst, Expr);
+ }
+
+ void addExpr(MCInst &Inst, const MCExpr *Expr) const{
+ // Add as immediate when possible. Null MCExpr = 0.
+ if (!Expr)
+ 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));
+ }
+
+ StringRef getToken() const {
+ assert(Kind == k_Token && "Invalid access!");
+ return StringRef(Tok.Data, Tok.Length);
+ }
+
+ MCRegister getReg() const override {
+ assert((Kind == k_Register) && "Invalid access!");
+ return Reg.Reg;
+ }
+
+ const MCExpr *getImm() const {
+ assert((Kind == k_Immediate) && "Invalid access!");
+ return Imm.Val;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateToken(StringRef Str, SMLoc S) {
+ auto Op = std::make_unique<SuperHOperand>(k_Token);
+ Op->Tok.Data = Str.data();
+ Op->Tok.Length = Str.size();
+ Op->StartLoc = S;
+ Op->EndLoc = S;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateReg(MCRegister Reg, unsigned Kind,
+ SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_Register);
+ Op->Reg.Reg = Reg;
+ Op->Reg.Kind = (SuperHOperand::RegisterKind)Kind;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_Immediate);
+ Op->Imm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ void print(raw_ostream &, const MCAsmInfo &) const override {
+
+ }
+};
+
+} // end anonymous namespace
+
+#define GET_MATCHER_IMPLEMENTATION
+#define GET_REGISTER_MATCHER
+#define GET_MNEMONIC_SPELL_CHECKER
+#define GET_MNEMONIC_CHECKER
+#include "SuperHGenAsmMatcher.inc"
+
+MCRegister SuperHAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegKind) {
+ RegKind = SuperHOperand::rk_None;
+ if(!Tok.is(AsmToken::Identifier))
+ return SH::NoRegister;
+
+ StringRef Name = Tok.getString();
+ MCRegister Reg = MatchRegisterName(Name.lower());
+ if (Reg) {
+
+ // XMTRX register.
+ if (Reg == SH::XMTRX) {
+ RegKind = SuperHOperand::rk_XMTRX;
+ return Reg;
+ }
+
+ // General purpose register class.
+ if (MRI.getRegClass(SH::GPRRegClassID).contains(Reg)) {
+ RegKind = SuperHOperand::rk_GPR;
+ return Reg;
+ }
+
+ // 32-bit float registers.
+ if (MRI.getRegClass(SH::FR32RegClassID).contains(Reg)) {
+ RegKind = SuperHOperand::rk_FR32;
+ return Reg;
+ }
+
+ // 64-bit float registers.
+ if (MRI.getRegClass(SH::FR64RegClassID).contains(Reg)) {
+ RegKind = SuperHOperand::rk_FR64;
+ return Reg;
+ }
+
+ // 128-bit vector registers.
+ if (MRI.getRegClass(SH::VEC128RegClassID).contains(Reg)) {
+ RegKind = SuperHOperand::rk_VEC128;
+ return Reg;
+ }
+ }
+ return SH::NoRegister;
+}
+
+bool SuperHAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) {
+ if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
+ return Error(StartLoc, "invalid register name");
+ return false;
+}
+
+ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) {
+ unsigned RegKind;
+ const AsmToken &Tok = Parser.getTok();
+ StartLoc = Tok.getLoc();
+ EndLoc = Tok.getEndLoc();
+
+ // SuperH Registers are in the form of an identifier.
+ Reg = SH::NoRegister;
+ if (getLexer().getKind() != AsmToken::Identifier)
+ return ParseStatus::NoMatch;
+
+ // Match.
+ Reg = matchRegisterName(Tok, RegKind);
+ if (RegKind == SuperHOperand::rk_None)
+ return ParseStatus::NoMatch;
+
+ // Consume the register.
+ Parser.Lex();
+ return ParseStatus::Success;
+}
+
+ParseStatus SuperHAsmParser::parseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
+ const AsmToken &Tok = Parser.getTok();
+ StartLoc = Tok.getLoc();
+ EndLoc = Tok.getEndLoc();
+
+ if (Tok.is(AsmToken::Integer)) {
+ Imm = Tok.getIntVal();
+ Parser.Lex();
+ return ParseStatus::Success;
+ }
+ return ParseStatus::Failure;
+}
+
+ParseStatus SuperHAsmParser::parseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc) {
+ const AsmToken &Tok = Parser.getTok();
+ StartLoc = Tok.getLoc();
+ EndLoc = Tok.getEndLoc();
+
+ Reg = matchRegisterName(Tok, RegKind);
+ if (Reg) {
+ Parser.Lex();
+ return ParseStatus::Success;
+ }
+ return ParseStatus::Failure;
+}
+
+ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
+ const AsmToken &Tok = Parser.getTok();
+ SMLoc StartLoc = getLexer().getLoc();
+ SMLoc EndLoc = getLexer().getLoc();
+
+ switch(Tok.getKind()) {
+ default: {
+ return ParseStatus::Failure;
+ }
+
+ // Immediates.
+ case llvm::AsmToken::Hash: {
+ Parser.Lex();
+ int64_t Imm;
+ if (parseImm(Imm, StartLoc, EndLoc).isSuccess()) {
+ const MCExpr *Val = MCConstantExpr::create(Imm, getContext());
+ Operands.push_back(SuperHOperand::CreateImm(Val, StartLoc, EndLoc));
+ return ParseStatus::Success;
+ }
+
+ // Un-lex on error
+ getLexer().UnLex(Tok);
+ return ParseStatus::Failure;
+ }
+
+ // Registers.
+ case AsmToken::Identifier: {
+ unsigned RegKind;
+ MCRegister Reg;
+ if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+ Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
+ return ParseStatus::Success;
+ }
+ return ParseStatus::Failure;
+ }
+ }
+}
+
+bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) {
+
+ // Match mnemonic.
+ bool MS = SuperHCheckMnemonic(Name, this->getAvailableFeatures(), 0);
+ if (!MS) {
+ return Error(NameLoc, "invalid instruction mnemonic" +
+ SuperHMnemonicSpellCheck(Name, getAvailableFeatures(), 0));
+ }
+
+ // Chomp name and add it to the operands.
+ Operands.push_back(SuperHOperand::CreateToken(Name, NameLoc));
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+
+ // Initial operand
+ if (!parseOperand(Operands).isSuccess()) {
+ SMLoc Loc = getLexer().getLoc();
+ return Error(Loc, "unexpected token");
+ }
+
+ // Followup operands.
+ while (getLexer().is(AsmToken::Comma)) {
+ Parser.Lex();
+
+ // Parse and remember operand.
+ if (!parseOperand(Operands).isSuccess()) {
+ SMLoc Loc = getLexer().getLoc();
+ return Error(Loc, "unexpected token");
+ }
+ }
+ }
+
+ // Consume EndOfStatement
+ Parser.Lex();
+ return false;
+}
+
+ParseStatus SuperHAsmParser::parseDirective(AsmToken DirectiveID) {
+ return ParseStatus::NoMatch;
+}
+
+bool SuperHAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ OperandVector &Operands, MCStreamer &Out,
+ uint64_t &ErrorInfo,
+ bool MatchingInlineAsm) {
+ MCInst Inst;
+ unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
+ switch(MatchResult) {
+ case Match_Success:
+ Inst.setLoc(IDLoc);
+ Out.emitInstruction(Inst, getSTI());
+ return false;
+ case Match_MissingFeature:
+ return Error(IDLoc, "instruction requires a CPU feature not currently enabled.");
+ case Match_InvalidOperand: {
+ SMLoc ErrorLoc = IDLoc;
+ if (ErrorInfo != ~0ULL) {
+ if (ErrorInfo >= Operands.size())
+ return Error(IDLoc, "too few operands for instruction");
+
+ ErrorLoc = ((SuperHOperand &)*Operands[ErrorInfo]).getStartLoc();
+ if (ErrorLoc == SMLoc())
+ ErrorLoc = IDLoc;
+ }
+
+ return Error(ErrorLoc, "invalid operand for instruction");
+ }
+ case Match_MnemonicFail:
+ return Error(IDLoc, "invalid instruction mnemonic");
+ }
+ return false;
+}
+
+
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
-LLVMInitializeSuperHAsmParser() { }
\ No newline at end of file
+LLVMInitializeSuperHAsmParser() {
+ RegisterMCAsmParser<SuperHAsmParser> A(getTheSuperHTarget());
+ RegisterMCAsmParser<SuperHAsmParser> B(getTheSuperHLETarget());
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index 64d7df4fb153e..df685cc0dbddb 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -2,14 +2,26 @@ add_llvm_component_group(SuperH)
set(LLVM_TARGET_DEFINITIONS SuperH.td)
-tablegen(LLVM SuperHGenRegisterInfo.inc -gen-register-info)
-#tablegen(LLVM SuperHGenInstrInfo.inc -gen-instr-info)
-tablegen(LLVM SuperHGenSubtargetInfo.inc -gen-subtarget)
+tablegen(LLVM SuperHGenAsmMatcher.inc -gen-asm-matcher)
+tablegen(LLVM SuperHGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM SuperHGenCallingConv.inc -gen-callingconv)
+tablegen(LLVM SuperHGenDAGISel.inc -gen-dag-isel)
+tablegen(LLVM SuperHGenDisassemblerTables.inc -gen-disassembler)
+tablegen(LLVM SuperHGenRegisterInfo.inc -gen-register-info)
+tablegen(LLVM SuperHGenInstrInfo.inc -gen-instr-info)
+#tablegen(LLVM SuperHGenMCCodeEmitter.inc -gen-emitter)
+tablegen(LLVM SuperHGenSDNodeInfo.inc -gen-sd-node-info -sdnode-namespace=SHISD)
+tablegen(LLVM SuperHGenSearchableTables.inc -gen-searchable-tables)
+tablegen(LLVM SuperHGenSubtargetInfo.inc -gen-subtarget)
add_public_tablegen_target(SuperHCommonTableGen)
add_llvm_target(SuperHCodeGen
SuperHTargetMachine.cpp
+ SuperHFrameLowering.cpp
+ SuperHRegisterInfo.cpp
+ SuperHInstrInfo.cpp
+ SuperHSubtarget.cpp
LINK_COMPONENTS
Analysis
@@ -31,5 +43,5 @@ add_llvm_target(SuperHCodeGen
)
add_subdirectory(AsmParser)
-add_subdirectory(TargetInfo)
-add_subdirectory(MCTargetDesc)
\ No newline at end of file
+add_subdirectory(MCTargetDesc)
+add_subdirectory(TargetInfo)
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
index 181ec4b281c14..a612d81272d0e 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
@@ -2,6 +2,8 @@ add_llvm_component_library(LLVMSuperHDesc
SuperHMCTargetDesc.cpp
SuperHMCAsmInfo.cpp
SuperHInstPrinter.cpp
+ SuperHELFObjectWriter.cpp
+ SuperHAsmBackend.cpp
LINK_COMPONENTS
MC
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
new file mode 100644
index 0000000000000..9e30207f6b32c
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -0,0 +1,80 @@
+//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/EndianStream.h"
+
+using namespace llvm;
+
+namespace {
+class SuperHAsmBackend : public MCAsmBackend {
+public:
+ SuperHAsmBackend(const MCSubtargetInfo &STI)
+ : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
+ ? llvm::endianness::little
+ : llvm::endianness::big) {}
+
+ std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
+ MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
+ void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
+ uint8_t *Data, uint64_t Value, bool IsResolved) override;
+
+ bool writeNopData(raw_ostream &OS, uint64_t Count,
+ const MCSubtargetInfo *STI) const override {
+
+ // If the count is not 4-byte aligned, we must be writing data into the
+ // text section (otherwise we have unaligned instructions, and thus have
+ // far bigger problems), so just write zeros instead.
+ OS.write_zeros(Count % 2);
+ return true;
+ }
+};
+
+class ELFSuperHAsmBackend : public SuperHAsmBackend {
+ Triple::OSType OSType;
+
+public:
+ ELFSuperHAsmBackend(const MCSubtargetInfo &STI, Triple::OSType OSType)
+ : SuperHAsmBackend(STI), OSType(OSType) {}
+
+ std::unique_ptr<MCObjectTargetWriter>
+ createObjectTargetWriter() const override {
+ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
+ return createSuperHELFObjectWriter(OSABI);
+ }
+};
+} // end anonymous namespace
+
+std::optional<MCFixupKind> SuperHAsmBackend::getFixupKind(StringRef Name) const {
+ return std::nullopt;
+}
+
+MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
+ return {"", 0, 2, 0};
+}
+
+void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
+ const MCValue &Target, uint8_t *Data,
+ uint64_t Value, bool IsResolved) {
+
+}
+
+MCAsmBackend *llvm::createSuperHAsmBackend(const Target &T,
+ const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options) {
+ return new ELFSuperHAsmBackend(STI, STI.getTargetTriple().getOS());
+}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
new file mode 100644
index 0000000000000..8df58460dc2a9
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -0,0 +1,55 @@
+//===-- SuperHELFObjectWriter.cpp - SuperH ELF Writer ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+namespace {
+ class SuperHELFObjectWriter : public MCELFObjectTargetWriter {
+ public:
+ SuperHELFObjectWriter(uint8_t OSABI)
+ : MCELFObjectTargetWriter(
+ false, OSABI,
+ ELF::EM_SH,
+ /*HasRelocationAddend*/ true) {}
+
+ ~SuperHELFObjectWriter() override = default;
+
+ protected:
+ unsigned getRelocType(const MCFixup &Fixup, const MCValue &Target,
+ bool IsPCRel) const override;
+
+ bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;
+ };
+}
+
+unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
+ const MCValue &Target,
+ bool IsPCRel) const {
+ return ELF::R_SH_NONE;
+}
+
+bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
+ unsigned Type) const {
+
+ return false;
+}
+
+std::unique_ptr<MCObjectTargetWriter>
+llvm::createSuperHELFObjectWriter(uint8_t OSABI) {
+ return std::make_unique<SuperHELFObjectWriter>(OSABI);
+}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 2b32ae9c389e0..95d0618ad6478 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -12,16 +12,25 @@
//===----------------------------------------------------------------------===//
#include "SuperHInstPrinter.h"
-// #include "SuperHInstrInfo.h"
#include "llvm/ADT/StringExtras.h"
-#include <llvm/MC/MCInst.h>
+#include "llvm/MC/MCInst.h"
+#include "llvm/Support/Debug.h"
using namespace llvm;
-#define DEBUG_TYPE "sh-isel"
+#define DEBUG_TYPE "sh-asmprinter"
+// The generated AsmMatcher SparcGenAsmWriter uses "SuperH" as the target
+// namespace. But SuperH backend uses "SH" as its namespace.
+namespace llvm {
+ namespace SuperH {
+ using namespace SH;
+ }
+}
+
+#define GET_INSTRUCTION_NAME
#define PRINT_ALIAS_INSTR
-// #include "SuperHGenAsmWriter.inc"
+#include "SuperHGenAsmWriter.inc"
SuperHInstPrinter::SuperHInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI) : MCInstPrinter(MAI, MII, MRI) {}
@@ -30,11 +39,6 @@ void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
OS << StringRef(getRegisterName(Reg)).lower();
}
-void SuperHInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
- const MCSubtargetInfo &STI, raw_ostream &OS) {
- printInstruction(MI, Address, OS);
-}
-
void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
@@ -52,18 +56,7 @@ void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostrea
}
}
-// TODO: Delete this placeholder.
-void SuperHInstPrinter::printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O) {
-
-}
-
-// TODO: Delete this placeholder.
-const char *SuperHInstPrinter::getRegisterName(MCRegister Reg) {
- return "r";
-}
-
-std::pair<const char *, uint64_t> SuperHInstPrinter::getMnemonic(const MCInst &MI) const {
- std::pair<const char *, uint64_t> Ret;
-
- return Ret;
+void SuperHInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
+ const MCSubtargetInfo &STI, raw_ostream &OS) {
+ printInstruction(MI, Address, OS);
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index d1b26b0e2f93d..ebdaca0d64915 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -14,9 +14,8 @@
#ifndef LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHINSTPRINTER_H
#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHINSTPRINTER_H
+#include "SuperHMCTargetDesc.h"
#include "llvm/MC/MCInstPrinter.h"
-#include <llvm/MC/MCExpr.h>
-#include <llvm/MC/MCInstrInfo.h>
namespace llvm {
@@ -31,13 +30,20 @@ class SuperHInstPrinter : public MCInstPrinter {
const MCRegisterInfo &MRI);
// Autogenerated by tablegen
+ std::pair<const char *, uint64_t>
+ getMnemonic(const MCInst &MI) const override;
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
+ void printCTILabel(const MCInst *MI, uint64_t Address, unsigned OpNum,
+ const MCSubtargetInfo &STI, raw_ostream &O);
+ bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS);
+ void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
+ unsigned OpIdx, unsigned PrintMethodIdx,
+ const MCSubtargetInfo &STI, raw_ostream &O);
static const char *getRegisterName(MCRegister Reg);
void printRegName(raw_ostream &OS, MCRegister Reg) override;
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &OS) override;
- std::pair<const char *, uint64_t> getMnemonic(const MCInst &MI) const override;
private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
index 323bb8e703ed8..7ee9d35209e9a 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -22,4 +22,5 @@ SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
const MCTargetOptions &Options)
: MCAsmInfoELF(Options) {
this->IsLittleEndian = TheTriple.isLittleEndian();
+ this->CommentString = ";";
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
index 4a8a31532c0e4..b99fb3387dbc5 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
@@ -31,6 +31,10 @@
using namespace llvm;
+#define GET_INSTRINFO_MC_DESC
+#define ENABLE_INSTR_PREDICATE_VERIFIER
+#include "SuperHGenInstrInfo.inc"
+
#define GET_REGINFO_MC_DESC
#include "SuperHGenRegisterInfo.inc"
@@ -39,13 +43,13 @@ using namespace llvm;
static MCInstrInfo *createSuperHMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
- // InitSuperHMCInstrInfo(X);
+ InitSuperHMCInstrInfo(X);
return X;
}
static MCRegisterInfo *createSuperHMCRegisterInfo(const Triple &TT) {
MCRegisterInfo *X = new MCRegisterInfo();
- // InitSuperHRegisterInfo(X);
+ InitSuperHMCRegisterInfo(X, SH::R0);
return X;
}
@@ -71,11 +75,7 @@ static MCAsmInfo *createSuperHMCAsmInfo(const MCRegisterInfo &MRI,
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeSuperHTargetMC() {
-
- // SuperH (big-endian)
- for (Target *T : {&getTheSuperHTarget()}) {
- // Register the MC asm info.
- TargetRegistry::RegisterMCAsmInfo(*T, createSuperHMCAsmInfo);
+ for (Target *T : {&getTheSuperHTarget(), &getTheSuperHLETarget()}) {
// Register the MC instruction info.
TargetRegistry::RegisterMCInstrInfo(*T, createSuperHMCInstrInfo);
@@ -85,26 +85,14 @@ LLVMInitializeSuperHTargetMC() {
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(*T, createSuperHMCSubtargetInfo);
-
- // Register the MCInstPrinter.
- TargetRegistry::RegisterMCInstPrinter(*T, createSuperHMCInstPrinter);
- }
-
- // SuperH (little-endian)
- for (Target *T : {&getTheSuperHLETarget()}) {
+
// Register the MC asm info.
TargetRegistry::RegisterMCAsmInfo(*T, createSuperHMCAsmInfo);
- // Register the MC instruction info.
- TargetRegistry::RegisterMCInstrInfo(*T, createSuperHMCInstrInfo);
-
- // Register the MC register info.
- TargetRegistry::RegisterMCRegInfo(*T, createSuperHMCRegisterInfo);
-
- // Register the MC subtarget info.
- TargetRegistry::RegisterMCSubtargetInfo(*T, createSuperHMCSubtargetInfo);
-
// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(*T, createSuperHMCInstPrinter);
+
+ // Register the AsmBackend
+ TargetRegistry::RegisterMCAsmBackend(*T, createSuperHAsmBackend);
}
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
index 6bb8d438df3ff..cee382a0aeab6 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
@@ -18,12 +18,6 @@
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/Support/DataTypes.h"
-#define GET_REGINFO_ENUM
-#include "SuperHGenRegisterInfo.inc"
-
-#define GET_SUBTARGETINFO_ENUM
-#include "SuperHGenSubtargetInfo.inc"
-
namespace llvm {
class MCAsmBackend;
class MCCodeEmitter;
@@ -39,6 +33,22 @@ class StringRef;
class raw_ostream;
class raw_pwrite_stream;
+MCAsmBackend *createSuperHAsmBackend(const Target &T, const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options);
+std::unique_ptr<MCObjectTargetWriter>
+createSuperHELFObjectWriter(uint8_t OSABI);
+
}
+#define GET_REGINFO_ENUM
+#include "SuperHGenRegisterInfo.inc"
+
+#define GET_INSTRINFO_ENUM
+#define GET_INSTRINFO_MC_HELPER_DECLS
+#include "SuperHGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_ENUM
+#include "SuperHGenSubtargetInfo.inc"
+
#endif // LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCTARGETDESC_H
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
new file mode 100644
index 0000000000000..931aeffd2c142
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -0,0 +1,19 @@
+//===-- SuperH.h - Top-level interface for SuperH representation *- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the entry points for global functions defined in the LLVM
+// SuperH back-end.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERH_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERH_H
+
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index 8ec78f923ee4e..a035fbdaff85d 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
include "llvm/Target/Target.td"
+include "llvm/TableGen/SearchableTable.td"
//===----------------------------------------------------------------------===//
// SuperH Subtarget features
@@ -69,21 +70,24 @@ def FeatureSH4A : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
include "SuperHSchedule.td"
-class Proc<string Name, list<SubtargetFeature> Features>
+class ProcModel<string Name, list<SubtargetFeature> Features>
: ProcessorModel<Name, GenericSuperHModel, Features>;
-def : Proc<"generic", [FeatureSH4]>;
-def : Proc<"sh1", [FeatureSH1]>;
-def : Proc<"sh2", [FeatureSH2]>;
-def : Proc<"sh3", [FeatureSH3]>;
-def : Proc<"sh4", [FeatureSH4]>;
-def : Proc<"sh4a", [FeatureSH4A]>;
+def : ProcModel<"generic", [FeatureSH4]>;
+def : ProcModel<"sh1", [FeatureSH1]>;
+def : ProcModel<"sh2", [FeatureSH2]>;
+def : ProcModel<"sh2e", [FeatureSH2E]>;
+def : ProcModel<"sh2a", [FeatureSH2A]>;
+def : ProcModel<"sh3", [FeatureSH3]>;
+def : ProcModel<"sh3e", [FeatureSH3E]>;
+def : ProcModel<"sh4", [FeatureSH4]>;
+def : ProcModel<"sh4a", [FeatureSH4A]>;
// NOTE: SEGA got some special variants of the SuperH family
// produced with some extra features enabled, defining them here.
-def : Proc<"dreamcast", [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
-def : Proc<"naomi", [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
-def : Proc<"saturn", [FeatureSH2]>;
+def : ProcModel<"dreamcast", [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
+def : ProcModel<"naomi", [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
+def : ProcModel<"saturn", [FeatureSH2]>;
//===----------------------------------------------------------------------===//
// Register File Description
@@ -96,6 +100,9 @@ include "SuperHRegisterInfo.td"
//===----------------------------------------------------------------------===//
include "SuperHInstrInfo.td"
+
+defm : RemapAllTargetPseudoPointerOperands<sh_ptr_rc>;
+
def SuperHInstrInfo : InstrInfo;
//===----------------------------------------------------------------------===//
@@ -117,12 +124,15 @@ def SuperHAsmWriter : AsmWriter {
//===---------------------------------------------------------------------===//
def SuperHAsmParser : AsmParser {
- let ShouldEmitMatchRegisterName = 0;
+ let ShouldEmitMatchRegisterName = 1;
let ShouldEmitMatchRegisterAltName = 0;
}
def SuperHAsmParserVariant : AsmParserVariant {
- int Variant = 0;
+ let Variant = 0;
+ let Name = "Hitachi";
+ let TokenizingCharacters = "[]*!#";
+ let CommentDelimiter = ";";
}
//===----------------------------------------------------------------------===//
@@ -132,5 +142,6 @@ def SuperHAsmParserVariant : AsmParserVariant {
def SuperH : Target {
let InstructionSet = SuperHInstrInfo;
let AssemblyParsers = [SuperHAsmParser];
+ let AssemblyParserVariants = [SuperHAsmParserVariant];
let AssemblyWriters = [SuperHAsmWriter];
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
new file mode 100644
index 0000000000000..ccd3340a45856
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -0,0 +1,44 @@
+//===- SuperHFrameLowering.cpp - SuperH Frame 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 SuperHTargetFrameLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "SuperHFrameLowering.h"
+#include "SuperHSubtarget.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+
+}
+
+void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+
+}
+
+bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+ return true;
+}
+
+MachineBasicBlock::iterator
+SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const {
+ return MBB.erase(I);
+}
+
+void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
+ RegScavenger *RS) const {
+
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
new file mode 100644
index 0000000000000..97eece4398642
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -0,0 +1,50 @@
+//===- SuperHFrameLowering.h - Define frame lowering for SuperH -*- 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 SuperHTargetFrameLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHFRAMELOWERING_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHFRAMELOWERING_H
+
+#include "llvm/CodeGen/TargetFrameLowering.h"
+
+namespace llvm {
+
+class SuperHSubtarget;
+
+class SuperHFrameLowering : public TargetFrameLowering {
+protected:
+ const SuperHSubtarget &STI;
+
+public:
+ explicit SuperHFrameLowering(const SuperHSubtarget &STI)
+ : TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
+ /*StackAlignment*/Align(4),
+ /*LocalAreaOffset*/0,
+ /*TransAl*/Align(4)),
+ STI(STI) {}
+
+ void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
+ void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
+
+ bool hasReservedCallFrame(const MachineFunction &MF) const override;
+ MachineBasicBlock::iterator
+ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const override;
+
+ void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
+ RegScavenger *RS) const override;
+};
+
+} // end namespace llvm
+
+
+#endif // end LLVM_LIB_TARGET_SUPERH_SUPERHFRAMELOWERING_H
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrData.td b/llvm/lib/Target/SuperH/SuperHInstrData.td
index d272437fff6b0..b66be593e634d 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrData.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrData.td
@@ -11,3 +11,46 @@
/// ISA.
///
//===----------------------------------------------------------------------===//
+
+
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+
+// imm -> Sign Extension -> Rn
+class Move_ir<bits<16> op, string opcodestr>
+ : SHInstOP_N4_I8<op, (outs GPR:$n), (ins imm8:$imm),
+ !strconcat(opcodestr, " $imm, $n")>;
+
+// Rm -> Rn
+class Move_rr<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
+ !strconcat(opcodestr, " $m, $n")>;
+
+// Rm -> (Rn)
+class Move_rri<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
+ !strconcat(opcodestr, " $m, $n")>;
+
+// (Rm) -> Sign Extension -> Rn
+class Move_rir<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
+ !strconcat(opcodestr, " $m, $n")>;
+}
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Namespace = "SH" in {
+ def MOV_ir : Move_ir<0b1110000000000000, "mov">;
+ def MOV_rr : Move_rr<0b0110000000000011, "mov">;
+ def MOVB_rri : Move_rri<0b0010000000000000, "mov.b">;
+ def MOVW_rri : Move_rri<0b0010000000000001, "mov.w">;
+ def MOVL_rri : Move_rri<0b0010000000000010, "mov.l">;
+ def MOVB_rir : Move_rir<0b0110000000000000, "mov.b">;
+ def MOVW_rir : Move_rir<0b0110000000000001, "mov.w">;
+ def MOVL_rir : Move_rir<0b0110000000000010, "mov.l">;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index de042add3c8c8..63f1d9cb76132 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -7,34 +7,205 @@
//
//===----------------------------------------------------------------------===//
-class SHInst<dag outs, dag ins, string asmstr, list<dag> pattern>
- : Instruction {
+//===----------------------------------------------------------------------===//
+//
+// The instruction formats in this file are defined based on the instruction
+// notation defined in the SuperH 4a specification, table 3.3.
+//
+// The SuperH architecture uses a "compressed" instruction set where all
+// instructions (except DSP instructions) are 16 bits wide, as such opcodes
+// often embed the registers, displacement, etc. within the instruction opcode
+// itself.
+//
+// SuperH Instructions are generally split up in the following categories:
+// * 0000nnnniiiiiiii (OP, Rn, imm) OP_N4_I8
+// * 0000nnnndddddddd (OP, Rn, disp) OP_N4_D8
+// * 0000nnnnmmmm0000 (OP, Rn, Rm, OP) OP_N4_M4
+// * 00000000nnnndddd (OP, Rn, disp) OP_N4_D4
+// * 00000000mmmmdddd (OP, Rm, disp) OP_M4_D4
+// * 0000nnnnmmmmdddd (OP, Rn, Rm, disp) OP_N4_M4_D4
+// * 00000000dddddddd (OP, disp) OP_D8
+// * 00000000iiiiiiii (OP, imm) OP_I8
+// * 0000nnnn00000000 (OP, Rn, OP) OP_N4
+// * 0000mmmm00000000 (OP, Rm, OP) OP_M4
+// * 0000000000000000 (OP) OP
+//
+// These classes are simplified by giving them a naming scheme based on their
+// encoding, eg. 0000nnnniiiiiiii is SHInstOP_N4_I8
+//
+// TODO: Implement the DSP extensions into this scheme.
+//
+//===----------------------------------------------------------------------===//
+
+// Base of all 16-bit SuperH instructions
+class SHInst <dag outs, dag ins, string asmstr, list<dag> pattern> : Instruction {
+ field bits<16> Inst;
+ field bits<16> SoftFail = 0;
+
+ bits<16> Opcode = 0;
let Namespace = "SH";
dag OutOperandList = outs;
dag InOperandList = ins;
let AsmString = asmstr;
let Pattern = pattern;
+ let Size = 2;
+}
+
+// SuperH Psuedo Instruction
+class SHPseudo<dag outs, dag ins, string asmstr="; error: this should not be emitted", list<dag> pattern = []>
+ : SHInst<outs, ins, asmstr, pattern> {
+ let isPseudo = 1;
+ let isCodeGenOnly = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction Formats
+//===----------------------------------------------------------------------===//
+
+class SHInstOP_N4_I8 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{3-0} = Opcode{3-0};
+
+ // Operands
+ bits<4> n;
+ bits<8> imm;
+ let Inst{7-4} = n;
+ let Inst{15-8} = imm;
+}
+
+class SHInstOP_N4_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
- field bits<16> Inst;
- let Size = 1;
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{3-0} = Opcode{3-0};
+
+ // Operands
+ bits<4> n;
+ bits<8> disp;
+ let Inst{7-4} = n;
+ let Inst{15-8} = disp;
}
-class SHDSPInst<dag outs, dag ins, string asmstr, list<dag> pattern>
- : Instruction {
+class SHInstOP_N4_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{3-0} = Opcode{3-0};
+ let Inst{15-11} = Opcode{15-11};
- let Namespace = "SH";
- dag OutOperandList = outs;
- dag InOperandList = ins;
- let AsmString = asmstr;
- let Pattern = pattern;
+ // Operands
+ bits<4> n;
+ bits<4> m;
+ let Inst{7-4} = n;
+ let Inst{11-8} = m;
+}
+
+class SHInstOP_N4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
- field bits<32> Inst;
- let Size = 2;
+ // Opcode
+ let Opcode = opcode;
+ let Inst{7-0} = Opcode{7-0};
+
+ // Operands
+ bits<4> n;
+ bits<4> disp;
+ let Inst{11-8} = n;
+ let Inst{15-12} = disp;
}
-// SH PSEUDO INSTRUCTION
-class SHPseudo<dag outs, dag ins, list<dag> pattern = []>
- : SHInst<outs, ins, "; error: this should not be emitted", pattern> {
- let isPseudo = 1;
+class SHInstOP_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{7-0} = Opcode{7-0};
+
+ // Operands
+ bits<4> m;
+ bits<4> disp;
+ let Inst{11-8} = m;
+ let Inst{15-12} = disp;
+}
+
+class SHInstOP_N4_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{3-0} = opcode{3-0};
+
+ // Operands
+ bits<4> n;
+ bits<4> m;
+ bits<4> disp;
+ let Inst{7-4} = n;
+ let Inst{11-8} = m;
+ let Inst{15-12} = disp;
+}
+
+class SHInstOP_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{7-0} = Opcode{7-0};
+
+ // Operands
+ bits<8> disp;
+ let Inst{15-8} = disp;
}
+
+class SHInstOP_I8 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{7-0} = Opcode{7-0};
+
+ // Operands
+ bits<8> imm;
+ let Inst{15-8} = imm;
+}
+
+class SHInstOP_N4 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{3-0} = Opcode{3-0};
+ let Inst{15-8} = Opcode{15-8};
+
+ // Operands
+ bits<4> n;
+ let Inst{7-4} = n;
+}
+
+class SHInstOP_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{3-0} = Opcode{3-0};
+ let Inst{15-8} = Opcode{15-8};
+
+ // Operands
+ bits<4> m;
+ let Inst{7-4} = m;
+}
+
+class SHInstOP <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst = Opcode;
+}
+
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
new file mode 100644
index 0000000000000..a4cc7447e2e48
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -0,0 +1,35 @@
+//===-- SuperHInstrInfo.cpp - SuperH 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 SuperH implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHInstrInfo.h"
+#include "SuperHSubtarget.h"
+#include "SuperHTargetMachine.h"
+#include "SuperH.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-instrinfo"
+
+#define GET_INSTRINFO_CTOR_DTOR
+#include "SuperHGenInstrInfo.inc"
+
+void SuperHInstrInfo::anchor() {}
+
+SuperHInstrInfo::SuperHInstrInfo(const SuperHSubtarget &ST)
+ : SuperHGenInstrInfo(ST, RI, SH::ADJCALLSTACKDOWN, SH::ADJCALLSTACKUP),
+ RI(ST), Subtarget(ST) { }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
new file mode 100644
index 0000000000000..458bde9bfc64a
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -0,0 +1,35 @@
+//===-- SuperHInstrInfo.h - SuperH 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 SuperH implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHINSTRINFO_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHINSTRINFO_H
+
+#include "SuperHRegisterInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+
+#define GET_INSTRINFO_HEADER
+#include "SuperHGenInstrInfo.inc"
+
+namespace llvm {
+
+class SuperHInstrInfo : public SuperHGenInstrInfo {
+ const SuperHRegisterInfo RI;
+ const SuperHSubtarget &Subtarget;
+ virtual void anchor();
+public:
+ explicit SuperHInstrInfo(const SuperHSubtarget &STI);
+};
+}
+
+#endif // end LLVM_LIB_TARGET_SUPERH_SUPERHINSTRINFO_H
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index f085dd1ec52bc..0b455ed4190f2 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -18,8 +18,26 @@
///
//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+// Instruction Formats
+//===----------------------------------------------------------------------===//
+
include "SuperHInstrFormats.td"
+//===----------------------------------------------------------------------===//
+// Instruction Patterns
+//===----------------------------------------------------------------------===//
+
+defvar SH = DefaultMode;
+def sh_ptr_rc : RegClassByHwMode<[SH], [GPR]>;
+
+// Both cases can use the same decoder method, so avoid the dispatch
+// by hwmode by setting an explicit DecoderMethod
+def ptr_op : RegisterOperand<sh_ptr_rc> {
+ let DecoderMethod = "DecodeIntRegsRegisterClass";
+}
+
+
//===----------------------------------------------------------------------===//
// SuperH Type Profiles
//===----------------------------------------------------------------------===//
@@ -50,9 +68,45 @@ def SHRet : SDNode<"SHISD::RET", SHSDT_Ret,
// Operands
//===----------------------------------------------------------------------===//
+class ImmAsmOperand<int width> : AsmOperandClass {
+ let Name = "Imm" # width;
+ let RenderMethod = "addImmOperands";
+}
+
+def imm8 : Operand<i8>, ImmLeaf<i32, [{return isInt<8>(Imm);}]> {
+ let ParserMatchClass = ImmAsmOperand<8>;
+ let EncoderMethod = "getImm";
+ let DecoderMethod = "decodeImmOperand<8>";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isInt<8>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// Basic Instructions
+//===----------------------------------------------------------------------===//
+
+// NOP instruction, does nothing.
+def NOP : SHInstOP<0b0000000000000000, (outs), (ins), "nop">;
//===----------------------------------------------------------------------===//
// Subsystems
//===----------------------------------------------------------------------===//
-include "SuperHInstrData.td"
\ No newline at end of file
+include "SuperHInstrData.td"
+
+//===----------------------------------------------------------------------===//
+// Pseudo instructions
+//===----------------------------------------------------------------------===//
+
+let Defs = [R0], Uses = [R0] in {
+def ADJCALLSTACKDOWN : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
+ "!ADJCALLSTACKDOWN $amt1, $amt2",
+ [(SHCallSeqStart timm:$amt1, timm:$amt2)]>;
+def ADJCALLSTACKUP : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
+ "!ADJCALLSTACKUP $amt1",
+ [(SHCallSeqEnd timm:$amt1, timm:$amt2)]>;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
new file mode 100644
index 0000000000000..32bdf20b8dd95
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -0,0 +1,78 @@
+//===-- SuperHRegisterInfo.h - SuperH Register Information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SuperH implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHRegisterInfo.h"
+#include "SuperHFrameLowering.h"
+#include "SuperHSubtarget.h"
+#include "SuperH.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-reginfo"
+
+#define GET_REGINFO_TARGET_DESC
+#include "SuperHGenRegisterInfo.inc"
+
+
+
+SuperHRegisterInfo::SuperHRegisterInfo(const SuperHSubtarget &ST)
+ : SuperHGenRegisterInfo(SH::R0, /*DwarfFlavour*/0, /*EHFlavor*/0,
+ /*PC*/SH::PC), Subtarget(ST) {}
+
+const TargetRegisterClass *SuperHRegisterInfo::intRegClass(unsigned Size) const {
+ return &SH::GPRRegClass;
+}
+
+BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+ BitVector Reserved(getNumRegs());
+
+ return Reserved;
+}
+
+bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
+ int SPAdj,
+ unsigned FIOperandNum,
+ RegScavenger *RS) const {
+ llvm_unreachable("Unsupported eliminateFrameIndex");
+ return true;
+}
+
+bool
+SuperHRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
+ return true;
+}
+
+bool
+SuperHRegisterInfo::requiresFrameIndexScavenging(
+ const MachineFunction &MF) const {
+ return true;
+}
+
+bool
+SuperHRegisterInfo::requiresFrameIndexReplacementScavenging(
+ const MachineFunction &MF) const {
+ return true;
+}
+
+bool
+SuperHRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
+ return true;
+}
+
+Register SuperHRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
+ llvm_unreachable("Unsupported getFrameRegister");
+}
+const MCPhysReg *SuperHRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
+ return nullptr;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
new file mode 100644
index 0000000000000..ed3200f7b0101
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -0,0 +1,53 @@
+//===-- SuperHRegisterInfo.h - SuperH Register Information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SuperH implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHREGISTERINFO_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHREGISTERINFO_H
+
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+
+#define GET_REGINFO_HEADER
+#include "SuperHGenRegisterInfo.inc"
+
+namespace llvm {
+class SuperHSubtarget;
+
+class SuperHRegisterInfo : public SuperHGenRegisterInfo {
+protected:
+ const SuperHSubtarget &Subtarget;
+
+public:
+ SuperHRegisterInfo(const SuperHSubtarget &Subtarget);
+
+ const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
+ BitVector getReservedRegs(const MachineFunction &MF) const override;
+
+ bool requiresRegisterScavenging(const MachineFunction &MF) const override;
+ bool requiresFrameIndexScavenging(const MachineFunction &MF) const override;
+ bool requiresFrameIndexReplacementScavenging(
+ const MachineFunction &MF) const override;
+
+ bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override;
+
+ bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
+ unsigned FIOperandNum,
+ RegScavenger *RS = nullptr) const override;
+
+ Register getFrameRegister(const MachineFunction &MF) const override;
+
+ const TargetRegisterClass *intRegClass(unsigned Size) const;
+};
+
+} // end namespace llvm
+
+#endif // end LLVM_LIB_TARGET_SUPERH_SUPERHREGISTERINFO_H
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index d8767915dfb45..fc4c05dadb994 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -144,7 +144,7 @@ let Namespace = "SH" in {
// 512-bit matrix register (shadows XF registers)
// TODO: Add proper subregisters here.
- def MtrxReg : MTRXReg<0, "xmtrx">;
+ def XMTRX : MTRXReg<0, "xmtrx">;
}
//===----------------------------------------------------------------------===//
@@ -180,7 +180,7 @@ def FR64 : RegisterClass<"SH", [f64], 64, (add
def VEC128 : RegisterClass<"SH", [v4f32], 128, (add FV0, FV4, FV8, FV12)>;
// Matrix register
-def MTRX512 : RegisterClass<"SH", [v16f32], 512, (add (sequence "FR%u", 0, 15), (sequence "XF%u", 0, 15))>;
+def XMTRX512 : RegisterClass<"SH", [v16f32], 512, (add (sequence "FR%u", 0, 15), (sequence "XF%u", 0, 15))>;
// Control registers
def CTRL : RegisterClass<"SH", [ i32 ], 32,
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
new file mode 100644
index 0000000000000..1f831a528a15a
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
@@ -0,0 +1,22 @@
+//===-- SuperHSubtarget.h - Define Subtarget for SuperH ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SuperH specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHSubtarget.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-subtarget"
+
+#define GET_SUBTARGETINFO_TARGET_DESC
+#define GET_SUBTARGETINFO_CTOR
+#include "SuperHGenSubtargetInfo.inc"
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.h b/llvm/lib/Target/SuperH/SuperHSubtarget.h
new file mode 100644
index 0000000000000..b5c38b7cb7ba4
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.h
@@ -0,0 +1,49 @@
+//===-- SuperHSubtarget.h - Define Subtarget for SuperH ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SuperH specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHSUBTARGET_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHSUBTARGET_H
+
+#define GET_SUBTARGETINFO_HEADER
+#include "SuperHGenSubtargetInfo.inc"
+
+
+namespace llvm {
+class SuperHSubtarget : public SuperHGenSubtargetInfo {
+ enum SuperHArchEnum {
+ SHDefault,
+ SH1,
+ SH2, SH2A, SH2E,
+ SH3, SH3E,
+ SH4, SH4A
+ };
+
+ SuperHArchEnum SHArchVersion;
+
+#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
+ bool ATTRIBUTE = DEFAULT;
+#include "SuperHGenSubtargetInfo.inc"
+
+#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
+ bool GETTER() const { return ATTRIBUTE; }
+#include "SuperHGenSubtargetInfo.inc"
+
+public:
+
+ /// ParseSubtargetFeatures - Parses features string setting specified
+ /// subtarget options. Definition of function is auto generated by tblgen.
+ void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
+};
+
+} // end namespace llvm
+
+#endif // end LLVM_LIB_TARGET_SUPERH_SUPERHSUBTARGET_H
\ No newline at end of file
>From 4a6aad64a0aea5bbdb4feffce35752f844fd2830 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 3 Jun 2026 10:23:34 +0200
Subject: [PATCH 07/39] Add MCCodeEmitter
---
llvm/lib/Target/SuperH/CMakeLists.txt | 2 +-
.../Target/SuperH/MCTargetDesc/CMakeLists.txt | 1 +
.../SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp | 1 +
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 101 ++++++++++++++++++
.../MCTargetDesc/SuperHMCTargetDesc.cpp | 3 +
.../SuperH/MCTargetDesc/SuperHMCTargetDesc.h | 6 +-
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 52 ++++-----
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 2 -
llvm/lib/TargetParser/Triple.cpp | 4 +
9 files changed, 141 insertions(+), 31 deletions(-)
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index df685cc0dbddb..f0d4a594242a9 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -9,7 +9,7 @@ tablegen(LLVM SuperHGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM SuperHGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM SuperHGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM SuperHGenInstrInfo.inc -gen-instr-info)
-#tablegen(LLVM SuperHGenMCCodeEmitter.inc -gen-emitter)
+tablegen(LLVM SuperHGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM SuperHGenSDNodeInfo.inc -gen-sd-node-info -sdnode-namespace=SHISD)
tablegen(LLVM SuperHGenSearchableTables.inc -gen-searchable-tables)
tablegen(LLVM SuperHGenSubtargetInfo.inc -gen-subtarget)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
index a612d81272d0e..c0bbc3c43df5b 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
@@ -1,4 +1,5 @@
add_llvm_component_library(LLVMSuperHDesc
+ SuperHMCCodeEmitter.cpp
SuperHMCTargetDesc.cpp
SuperHMCAsmInfo.cpp
SuperHInstPrinter.cpp
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
index 7ee9d35209e9a..a98647bc36f26 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -23,4 +23,5 @@ SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
: MCAsmInfoELF(Options) {
this->IsLittleEndian = TheTriple.isLittleEndian();
this->CommentString = ";";
+ this->SeparatorString = "\n";
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
new file mode 100644
index 0000000000000..380247543dff6
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -0,0 +1,101 @@
+//===-- SuperHGenMCCodeEmitter.cpp - Convert SuperH code to machine code --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SuperHMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "SuperHMCTargetDesc.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/bit.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/EndianStream.h"
+
+
+using namespace llvm;
+
+#define DEBUG_TYPE "mccodeemitter"
+
+STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
+
+namespace {
+
+class SuperHMCCodeEmitter : public MCCodeEmitter {
+ MCContext &Ctx;
+
+public:
+ SuperHMCCodeEmitter(const MCInstrInfo &, MCContext &ctx)
+ : Ctx(ctx) {}
+ SuperHMCCodeEmitter(const SuperHMCCodeEmitter &) = delete;
+ SuperHMCCodeEmitter &operator=(const SuperHMCCodeEmitter &) = delete;
+ ~SuperHMCCodeEmitter() override = default;
+
+ void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const override;
+
+ // getBinaryCodeForInstr - TableGen'erated function for getting the
+ // binary encoding for an instruction.
+ uint64_t getBinaryCodeForInstr(const MCInst &MI,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) 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,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+};
+
+} // end namespace
+
+#include "SuperHGenMCCodeEmitter.inc"
+
+void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
+ SmallVectorImpl<char> &CB,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+
+ // All base instructions are 16-bit in SuperH asm
+ uint16_t Bits = (uint16_t)getBinaryCodeForInstr(MI, Fixups, STI);
+ support::endian::write(CB, Bits, Ctx.getAsmInfo().isLittleEndian()
+ ? llvm::endianness::little
+ : llvm::endianness::big);
+
+ ++MCNumEmitted;
+}
+
+unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ if (MO.isReg())
+ return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
+
+ if (MO.isImm())
+ return MO.getImm();
+
+ return 0;
+}
+
+MCCodeEmitter *llvm::createSuperHMCCodeEmitter(const MCInstrInfo &MCII,
+ MCContext &Ctx) {
+ return new SuperHMCCodeEmitter(MCII, Ctx);
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
index b99fb3387dbc5..15f6cc8195b54 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
@@ -92,6 +92,9 @@ LLVMInitializeSuperHTargetMC() {
// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(*T, createSuperHMCInstPrinter);
+ // Register the MCCodeEmitter.
+ TargetRegistry::RegisterMCCodeEmitter(*T, createSuperHMCCodeEmitter);
+
// Register the AsmBackend
TargetRegistry::RegisterMCAsmBackend(*T, createSuperHAsmBackend);
}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
index cee382a0aeab6..5d060e597c149 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
@@ -33,12 +33,14 @@ class StringRef;
class raw_ostream;
class raw_pwrite_stream;
+MCCodeEmitter *createSuperHMCCodeEmitter(const MCInstrInfo &MCII,
+ MCContext &Ctx);
+
MCAsmBackend *createSuperHAsmBackend(const Target &T, const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options);
-std::unique_ptr<MCObjectTargetWriter>
-createSuperHELFObjectWriter(uint8_t OSABI);
+std::unique_ptr<MCObjectTargetWriter> createSuperHELFObjectWriter(uint8_t OSABI);
}
#define GET_REGINFO_ENUM
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index 63f1d9cb76132..fbe8b2f0fd501 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -68,13 +68,13 @@ class SHInstOP_N4_I8 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{3-0} = Opcode{3-0};
+ let Inst{15-12} = Opcode{15-12};
// Operands
bits<4> n;
bits<8> imm;
- let Inst{7-4} = n;
- let Inst{15-8} = imm;
+ let Inst{11-8} = n;
+ let Inst{7-0} = imm;
}
class SHInstOP_N4_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -83,13 +83,13 @@ class SHInstOP_N4_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{3-0} = Opcode{3-0};
+ let Inst{15-12} = Opcode{15-12};
// Operands
bits<4> n;
bits<8> disp;
- let Inst{7-4} = n;
- let Inst{15-8} = disp;
+ let Inst{11-8} = n;
+ let Inst{7-0} = disp;
}
class SHInstOP_N4_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -97,14 +97,14 @@ class SHInstOP_N4_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{3-0} = Opcode{3-0};
let Inst{15-11} = Opcode{15-11};
+ let Inst{3-0} = Opcode{3-0};
// Operands
bits<4> n;
bits<4> m;
- let Inst{7-4} = n;
- let Inst{11-8} = m;
+ let Inst{11-8} = n;
+ let Inst{7-4} = m;
}
class SHInstOP_N4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -112,13 +112,13 @@ class SHInstOP_N4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{7-0} = Opcode{7-0};
+ let Inst{15-8} = Opcode{15-8};
// Operands
bits<4> n;
bits<4> disp;
- let Inst{11-8} = n;
- let Inst{15-12} = disp;
+ let Inst{11-8} = disp;
+ let Inst{15-12} = n;
}
class SHInstOP_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -126,13 +126,13 @@ class SHInstOP_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{7-0} = Opcode{7-0};
+ let Inst{15-8} = Opcode{15-8};
// Operands
bits<4> m;
bits<4> disp;
- let Inst{11-8} = m;
- let Inst{15-12} = disp;
+ let Inst{11-8} = disp;
+ let Inst{15-12} = m;
}
class SHInstOP_N4_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -140,15 +140,15 @@ class SHInstOP_N4_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{3-0} = opcode{3-0};
+ let Inst{15-12} = Opcode{15-12};
// Operands
bits<4> n;
bits<4> m;
bits<4> disp;
- let Inst{7-4} = n;
- let Inst{11-8} = m;
- let Inst{15-12} = disp;
+ let Inst{11-8} = n;
+ let Inst{7-4} = m;
+ let Inst{0-3} = disp;
}
class SHInstOP_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -156,11 +156,11 @@ class SHInstOP_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{7-0} = Opcode{7-0};
+ let Inst{15-8} = Opcode{15-8};
// Operands
bits<8> disp;
- let Inst{15-8} = disp;
+ let Inst{7-0} = disp;
}
class SHInstOP_I8 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -168,11 +168,11 @@ class SHInstOP_I8 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{7-0} = Opcode{7-0};
+ let Inst{15-8} = Opcode{15-8};
// Operands
bits<8> imm;
- let Inst{15-8} = imm;
+ let Inst{7-0} = imm;
}
class SHInstOP_N4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -180,12 +180,12 @@ class SHInstOP_N4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{3-0} = Opcode{3-0};
let Inst{15-8} = Opcode{15-8};
+ let Inst{3-0} = Opcode{3-0};
// Operands
bits<4> n;
- let Inst{7-4} = n;
+ let Inst{11-8} = n;
}
class SHInstOP_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -198,7 +198,7 @@ class SHInstOP_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Operands
bits<4> m;
- let Inst{7-4} = m;
+ let Inst{11-8} = m;
}
class SHInstOP <bits<16> opcode, dag outs, dag ins, string asmstr>
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 0b455ed4190f2..e137158b352d5 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -75,8 +75,6 @@ class ImmAsmOperand<int width> : AsmOperandClass {
def imm8 : Operand<i8>, ImmLeaf<i32, [{return isInt<8>(Imm);}]> {
let ParserMatchClass = ImmAsmOperand<8>;
- let EncoderMethod = "getImm";
- let DecoderMethod = "decodeImmOperand<8>";
let MCOperandPredicate = [{
int64_t Imm;
if (MCOp.evaluateAsConstantImm(Imm))
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 1e9d675ff5162..3e62300a726de 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -692,6 +692,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("riscv32be", riscv32be)
.Case("riscv64be", riscv64be)
.Case("hexagon", hexagon)
+ .Case("sh", sh)
+ .Case("sh_le", sh_le)
.Case("sparc", sparc)
.Case("sparcel", sparcel)
.Case("sparcv9", sparcv9)
@@ -845,6 +847,8 @@ Triple::ArchType Triple::parseArch(StringRef ArchName) {
.Case("riscv64be", Triple::riscv64be)
.Case("hexagon", Triple::hexagon)
.Cases({"s390x", "systemz"}, Triple::systemz)
+ .Case("sh", Triple::sh)
+ .Case("sh_le", Triple::sh_le)
.Case("sparc", Triple::sparc)
.Case("sparcel", Triple::sparcel)
.Cases({"sparcv9", "sparc64"}, Triple::sparcv9)
>From 83e39d37d678ce09ad4c026793d8cba7a0d45e5d Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 3 Jun 2026 10:42:10 +0200
Subject: [PATCH 08/39] Clean up instructions a tiny bit
---
.../Target/SuperH/SuperHInstrArithmetic.td | 22 ++++++++++
llvm/lib/Target/SuperH/SuperHInstrData.td | 42 ++++---------------
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 35 ++++++++++++++++
3 files changed, 65 insertions(+), 34 deletions(-)
create mode 100644 llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
diff --git a/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td b/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
new file mode 100644
index 0000000000000..a8f61a2310963
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
@@ -0,0 +1,22 @@
+//===-- SuperHInstrArithmetic.td - SuperH Arithmetic Instructions -*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes all of the arithmetic instructions in the SuperH
+/// ISA.
+///
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Namespace = "SH" in {
+ def ADD_ir : Op_rr<0b0011100000000000, "add">;
+ def ADD_rr : Op_rr<0b0011000000001100, "add">;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrData.td b/llvm/lib/Target/SuperH/SuperHInstrData.td
index b66be593e634d..983f0ba58024a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrData.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrData.td
@@ -13,44 +13,18 @@
//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-// Instruction Class Templates
-//===----------------------------------------------------------------------===//
-
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
-
-// imm -> Sign Extension -> Rn
-class Move_ir<bits<16> op, string opcodestr>
- : SHInstOP_N4_I8<op, (outs GPR:$n), (ins imm8:$imm),
- !strconcat(opcodestr, " $imm, $n")>;
-
-// Rm -> Rn
-class Move_rr<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
- !strconcat(opcodestr, " $m, $n")>;
-
-// Rm -> (Rn)
-class Move_rri<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
- !strconcat(opcodestr, " $m, $n")>;
-
-// (Rm) -> Sign Extension -> Rn
-class Move_rir<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
- !strconcat(opcodestr, " $m, $n")>;
-}
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
let Namespace = "SH" in {
- def MOV_ir : Move_ir<0b1110000000000000, "mov">;
- def MOV_rr : Move_rr<0b0110000000000011, "mov">;
- def MOVB_rri : Move_rri<0b0010000000000000, "mov.b">;
- def MOVW_rri : Move_rri<0b0010000000000001, "mov.w">;
- def MOVL_rri : Move_rri<0b0010000000000010, "mov.l">;
- def MOVB_rir : Move_rir<0b0110000000000000, "mov.b">;
- def MOVW_rir : Move_rir<0b0110000000000001, "mov.w">;
- def MOVL_rir : Move_rir<0b0110000000000010, "mov.l">;
+ def MOV_ir : Op_ir<0b1110000000000000, "mov">;
+ def MOV_rr : Op_rr<0b0110000000000011, "mov">;
+ def MOVB_rri : Store_rr<0b0010000000000000, "mov.b">;
+ def MOVW_rri : Store_rr<0b0010000000000001, "mov.w">;
+ def MOVL_rri : Store_rr<0b0010000000000010, "mov.l">;
+ def MOVB_rir : Load_rr<0b0110000000000000, "mov.b">;
+ def MOVW_rir : Load_rr<0b0110000000000001, "mov.w">;
+ def MOVL_rir : Load_rr<0b0110000000000010, "mov.l">;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index e137158b352d5..56b362c5fdbbd 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -83,18 +83,53 @@ def imm8 : Operand<i8>, ImmLeaf<i32, [{return isInt<8>(Imm);}]> {
}];
}
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+
+ // imm -> Sign Extension -> Rn
+ class Op_ir<bits<16> op, string opcodestr>
+ : SHInstOP_N4_I8<op, (outs GPR:$n), (ins imm8:$imm),
+ !strconcat(opcodestr, " $imm, $n")>;
+
+ // Rm -> Rn
+ class Op_rr<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
+ !strconcat(opcodestr, " $m, $n")>;
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
+
+ // Rm -> (Rn)
+ class Store_rr<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
+ !strconcat(opcodestr, " $m, $n")>;
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
+
+ // (Rm) -> Sign Extension -> Rn
+ class Load_rr<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
+ !strconcat(opcodestr, " $m, $n")>;
+}
+
//===----------------------------------------------------------------------===//
// Basic Instructions
//===----------------------------------------------------------------------===//
// NOP instruction, does nothing.
def NOP : SHInstOP<0b0000000000000000, (outs), (ins), "nop">;
+def RTS : SHInstOP<0b0000000000001011, (outs), (ins), "rts">;
//===----------------------------------------------------------------------===//
// Subsystems
//===----------------------------------------------------------------------===//
include "SuperHInstrData.td"
+include "SuperHInstrArithmetic.td"
//===----------------------------------------------------------------------===//
// Pseudo instructions
>From 2c3898810abcca79cfbf2181731201bdfa7cd1cc Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 5 Jun 2026 04:09:27 +0200
Subject: [PATCH 09/39] add a few more arithmetic instructions
---
.../lib/Target/SuperH/SuperHInstrArithmetic.td | 11 +++++++++--
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 4 ++--
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 18 ++++++++++++++++--
3 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td b/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
index a8f61a2310963..8b4add0af3314 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
@@ -17,6 +17,13 @@
//===----------------------------------------------------------------------===//
let Namespace = "SH" in {
- def ADD_ir : Op_rr<0b0011100000000000, "add">;
- def ADD_rr : Op_rr<0b0011000000001100, "add">;
+ def ADD_ir : Op_ir<0b0011100000000000, "add">;
+ def ADD_rr : Op_rr<0b0011000000001100, "add">;
+ def ADDC_rr : Op_rr<0b0011000000001110, "addc">;
+ def ADDV_rr : Op_rr<0b0011000000001111, "addv">;
+ def DIV0S_rr : Op_rr<0b0010000000000111, "div0s">;
+ def DIV0U_rr : Op<0b0000000000011001, "div0u">;
+ def DIV1_rr : Op_rr<0b0011000000000100, "div1">;
+ def DIVS_rr0 : Op_rr0<0b0100000010010100, "divs">;
+ def DIVU_rr0 : Op_rr0<0b0100000010000100, "divu">;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index fbe8b2f0fd501..af2f4d4a8f394 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -181,7 +181,7 @@ class SHInstOP_N4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
let Inst{15-8} = Opcode{15-8};
- let Inst{3-0} = Opcode{3-0};
+ let Inst{7-0} = Opcode{7-0};
// Operands
bits<4> n;
@@ -193,8 +193,8 @@ class SHInstOP_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Opcode
let Opcode = opcode;
- let Inst{3-0} = Opcode{3-0};
let Inst{15-8} = Opcode{15-8};
+ let Inst{7-0} = Opcode{7-0};
// Operands
bits<4> m;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 56b362c5fdbbd..13761e4447da0 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -89,6 +89,20 @@ def imm8 : Operand<i8>, ImmLeaf<i32, [{return isInt<8>(Imm);}]> {
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+ // No-arg instruction
+ class Op<bits<16> op, string opcodestr>
+ : SHInstOP<op, (outs), (ins), opcodestr>;
+
+ // Rn
+ class Op_r<bits<16> op, string opcodestr>
+ : SHInstOP_N4<op, (outs GPR:$n), (ins),
+ !strconcat(opcodestr, " $n")>;
+
+ // R0, Rn
+ class Op_rr0<bits<16> op, string opcodestr>
+ : SHInstOP_N4<op, (outs GPR:$n), (ins),
+ !strconcat(opcodestr, " r0, $n")>;
+
// imm -> Sign Extension -> Rn
class Op_ir<bits<16> op, string opcodestr>
: SHInstOP_N4_I8<op, (outs GPR:$n), (ins imm8:$imm),
@@ -121,8 +135,8 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
//===----------------------------------------------------------------------===//
// NOP instruction, does nothing.
-def NOP : SHInstOP<0b0000000000000000, (outs), (ins), "nop">;
-def RTS : SHInstOP<0b0000000000001011, (outs), (ins), "rts">;
+def NOP : Op<0b0000000000000000, "nop">;
+def RTS : Op<0b0000000000001011, "rts">;
//===----------------------------------------------------------------------===//
// Subsystems
>From e7ebd09961971b7ca776ab08c6c0d21ea04ca5a7 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 6 Aug 2026 11:59:45 +0200
Subject: [PATCH 10/39] Update specifiers and ELF info
---
clang/include/clang/Basic/Specifiers.h | 2 ++
llvm/include/llvm/BinaryFormat/ELF.h | 10 +++++-----
.../include/llvm/BinaryFormat/ELFRelocs/SuperH.def | 14 +++++++++++++-
3 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 8da6fd4cf454a..60df557d8fa8d 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -313,6 +313,8 @@ namespace clang {
CC_RISCVVLSCall_16384, // __attribute__((riscv_vls_cc(16384)))
CC_RISCVVLSCall_32768, // __attribute__((riscv_vls_cc(32768)))
CC_RISCVVLSCall_65536, // __attribute__((riscv_vls_cc(65536)))
+ CC_SH_RENESAS, // __attribute__((sh_renesas))
+ CC_SH_WinCE, // __attribute__((sh_wince))
};
/// Checks whether the given calling convention supports variadic
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 6bc9e2a6168d2..93d4f7fc2f4da 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -727,17 +727,17 @@ enum {
#undef ELF_RISCV_NONSTANDARD_RELOC
};
-// ELF Relocation types for SuperH
-enum {
-#include "ELFRelocs/SuperH.def"
-};
-
enum {
// Symbol may follow different calling convention than the standard calling
// convention.
STO_RISCV_VARIANT_CC = 0x80
};
+// ELF Relocation types for SuperH
+enum {
+#include "ELFRelocs/SuperH.def"
+};
+
// ELF Relocation types for S390/zSeries
enum {
#include "ELFRelocs/SystemZ.def"
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
index 031ecbc6a6448..cc06af4cbb968 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
@@ -7,6 +7,8 @@
// See: https://www.renesas.com/en/document/mat/superh-cc-compiler-package-v904-users-manual?r=1169516
ELF_RELOC(R_SH_NONE, 0)
+ELF_RELOC(R_SH_DIR32, 1)
+ELF_RELOC(R_SH_REL32, 2)
ELF_RELOC(R_SH_GOT32, 160)
ELF_RELOC(R_SH_GOT_LOW16, 169)
ELF_RELOC(R_SH_GOT_MEDLOW16, 170)
@@ -35,4 +37,14 @@ ELF_RELOC(R_SH_GOTPC, 167)
ELF_RELOC(R_SH_GOTPC_LOW16, 185)
ELF_RELOC(R_SH_GOTPC_MEDLOW16, 186)
ELF_RELOC(R_SH_GOTPC_MEDHI16, 187)
-ELF_RELOC(R_SH_GOTPC_HI16, 188)
\ No newline at end of file
+ELF_RELOC(R_SH_GOTPC_HI16, 188)
+ELF_RELOC(R_SH_COPY, 162)
+ELF_RELOC(R_SH_COPY64, 193)
+ELF_RELOC(R_SH_GLOB_DAT, 163)
+ELF_RELOC(R_SH_GLOB_DAT64, 194)
+ELF_RELOC(R_SH_JMP_SLOT, 164)
+ELF_RELOC(R_SH_JMP_SLOT64, 195)
+ELF_RELOC(R_SH_RELATIVE, 165)
+ELF_RELOC(R_SH_RELATIVE64, 196)
+ELF_RELOC(R_SH_64, 254)
+ELF_RELOC(R_SH_64_PCREL, 255)
\ No newline at end of file
>From 44fab6b1904e1e71c156cbb431b0d6011959797b Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 6 Aug 2026 12:00:49 +0200
Subject: [PATCH 11/39] Add support for arithmetic, branching and fixups
Fixups are currently not fully complete and does not handle
12 bit displacements fully yet.
---
.../SuperH/AsmParser/SuperHAsmParser.cpp | 280 ++++++++++++++++--
.../SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 186 +++++++++---
.../SuperH/MCTargetDesc/SuperHAsmBackend.h | 48 +++
.../MCTargetDesc/SuperHELFObjectWriter.cpp | 7 +-
.../SuperH/MCTargetDesc/SuperHFixupKinds.h | 46 +++
.../SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp | 2 +
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 33 ++-
llvm/lib/Target/SuperH/SuperH.td | 3 +-
llvm/lib/Target/SuperH/SuperHCallingConv.td | 60 ++++
.../Target/SuperH/SuperHInstrArithmetic.td | 68 ++++-
llvm/lib/Target/SuperH/SuperHInstrBranch.td | 76 +++++
llvm/lib/Target/SuperH/SuperHInstrData.td | 160 +++++++++-
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 57 ++--
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 130 +++++---
llvm/lib/Target/SuperH/SuperHRegisterInfo.td | 73 +++--
15 files changed, 1040 insertions(+), 189 deletions(-)
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
create mode 100644 llvm/lib/Target/SuperH/SuperHCallingConv.td
create mode 100644 llvm/lib/Target/SuperH/SuperHInstrBranch.td
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 722c81cbcd0ea..5fa685f814828 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -18,6 +18,7 @@
#include "llvm/MC/MCRegister.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCValue.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/MC/MCAsmMacro.h"
#include "llvm/MC/MCContext.h"
@@ -37,7 +38,9 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/DebugLog.h"
#include "iostream"
+#include <cstddef>
#include <sstream>
#include <system_error>
@@ -56,6 +59,12 @@ namespace SuperH {
namespace {
class SuperHOperand;
+// Helper that gets a string from a SMLoc pair.
+StringRef StrFromLoc(SMLoc StartLoc, SMLoc EndLoc) {
+ ptrdiff_t Length = (ptrdiff_t)(EndLoc.getPointer()-StartLoc.getPointer());
+ return StringRef(StartLoc.getPointer(), Length);
+}
+
class SuperHAsmParser : public MCTargetAsmParser {
MCAsmParser &Parser;
const MCRegisterInfo &MRI;
@@ -68,10 +77,12 @@ class SuperHAsmParser : public MCTargetAsmParser {
MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override;
ParseStatus parseDirective(AsmToken DirectiveID) override;
+ bool parseGNUAttribute(SMLoc L);
bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
uint64_t &ErrorInfo,
bool MatchingInlineAsm) override;
+
ParseStatus parseOperand(OperandVector &Operands);
ParseStatus parseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc);
ParseStatus parseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc);
@@ -101,12 +112,22 @@ class SuperHOperand : public MCParsedAsmOperand {
};
private:
+
+ // These are set up as bitflags to allow general comparisons
+ // to happen with some simple bit masking.
enum KindTy {
- k_Token,
- k_Register,
- k_Immediate,
- } Kind;
+ k_Token = 0x001,
+ k_Register = 0x002,
+ k_Immediate = 0x004,
+ k_Displacement = 0x008,
+ k_IndirectReg = 0x010,
+ k_IndirectRegInc = 0x020,
+ k_IndirectRegDec = 0x040,
+ k_IndirectIndex = 0x080,
+ k_Expression = 0x100
+ };
+ unsigned Kind;
SMLoc StartLoc, EndLoc;
struct Token {
@@ -123,29 +144,42 @@ class SuperHOperand : public MCParsedAsmOperand {
const MCExpr *Val;
};
+ struct DispOp {
+ const MCExpr *Val;
+ };
+
+ struct ExprOp {
+ const MCExpr *Val;
+ };
+
struct MemOp {
MCRegister Base;
MCRegister OffsetReg;
- const MCExpr *Off;
+ const MCExpr *Offset;
};
union {
struct Token Tok;
struct RegOp Reg;
struct ImmOp Imm;
+ struct DispOp Disp;
struct MemOp Mem;
+ struct ExprOp Expr;
unsigned ASI;
unsigned Prefetch;
};
public:
SuperHOperand(KindTy K) : Kind(K) {}
+ SuperHOperand(unsigned K) : Kind(K) {}
bool isToken() const override { return Kind == k_Token; }
bool isImm() const override { return Kind == k_Immediate; }
bool isReg() const override { return Kind == k_Register; }
- bool isMem() const override { return false; }
- bool isImm8() const { return Kind == k_Immediate; }
+ bool isDisp() const { return Kind == k_Displacement; }
+ bool isMem() const override { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec | k_IndirectIndex)) != 0; }
+ bool isIndirectReg() const { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec)) != 0; }
+ bool isAnyReg() const { return isReg() || isIndirectReg(); }
SMLoc getStartLoc() const override { return StartLoc; }
SMLoc getEndLoc() const override { return EndLoc; }
@@ -155,10 +189,21 @@ class SuperHOperand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::createReg(getReg()));
}
+ void addMemOperands(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!");
const MCExpr *Expr = getImm();
- addExpr(Inst, Expr);
+ this->addExpr(Inst, Expr);
+ }
+
+ void addDispOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCExpr *Expr = getDisp();
+ this->addExpr(Inst, Expr);
}
void addExpr(MCInst &Inst, const MCExpr *Expr) const{
@@ -177,15 +222,25 @@ class SuperHOperand : public MCParsedAsmOperand {
}
MCRegister getReg() const override {
- assert((Kind == k_Register) && "Invalid access!");
- return Reg.Reg;
+ assert(this->isAnyReg() && "Invalid access!");
+ return this->isReg() ? Reg.Reg : Mem.Base;
}
const MCExpr *getImm() const {
- assert((Kind == k_Immediate) && "Invalid access!");
+ assert((Kind & k_Immediate) && "Invalid access!");
return Imm.Val;
}
+ const MCExpr *getDisp() const {
+ assert((Kind & k_Displacement) && "Invalid access!");
+ return Disp.Val;
+ }
+
+ const MCExpr *getOffset() const {
+ assert((Kind == k_IndirectIndex) && "Invalid access!");
+ return Mem.Offset;
+ }
+
static std::unique_ptr<SuperHOperand> CreateToken(StringRef Str, SMLoc S) {
auto Op = std::make_unique<SuperHOperand>(k_Token);
Op->Tok.Data = Str.data();
@@ -196,7 +251,7 @@ class SuperHOperand : public MCParsedAsmOperand {
}
static std::unique_ptr<SuperHOperand> CreateReg(MCRegister Reg, unsigned Kind,
- SMLoc S, SMLoc E) {
+ SMLoc S, SMLoc E) {
auto Op = std::make_unique<SuperHOperand>(k_Register);
Op->Reg.Reg = Reg;
Op->Reg.Kind = (SuperHOperand::RegisterKind)Kind;
@@ -213,8 +268,101 @@ class SuperHOperand : public MCParsedAsmOperand {
return Op;
}
- void print(raw_ostream &, const MCAsmInfo &) const override {
+ static std::unique_ptr<SuperHOperand> CreateDisp(const MCExpr *Val, SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_Displacement);
+ Op->Imm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateSymRef(const MCExpr *Val, SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_Immediate | k_Displacement);
+ Op->Imm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateIReg(MCRegister Reg, SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_IndirectReg);
+ Op->Mem.Base = Reg;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateIRegInc(MCRegister Reg, SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_IndirectRegInc);
+ Op->Mem.Base = Reg;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateIRegDec(MCRegister Reg, SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_IndirectRegDec);
+ Op->Mem.Base = Reg;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateIIndex(MCRegister Base, MCRegister OffsetReg,
+ const MCExpr *Offset,
+ SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_IndirectIndex);
+ Op->Mem.Base = Base;
+ Op->Mem.OffsetReg = OffsetReg;
+ Op->Mem.Offset = Offset;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateExpr(const MCExpr *Expr,
+ SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SuperHOperand>(k_Expression);
+ Op->Expr.Val = Expr;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<SuperHOperand> CreateFromExpr(const MCExpr *Expr,
+ SMLoc S, SMLoc E) {
+ if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
+ return CreateDisp(CE, S, E);
+ if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
+ return CreateDisp(SRE, S, E);
+ }
+
+ return CreateExpr(Expr, S, E);
+ }
+
+ void print(raw_ostream &OS, const MCAsmInfo &I) const override {
+
+ // Tokens don't have Start+End locations.
+ if (Kind == k_Token) {
+ OS << StringRef(Tok.Data, Tok.Length);
+ return;
+ }
+
+ // Indirect register has @ prefix.
+ if (isIndirectReg())
+ OS << "@";
+
+ // Pre-decrement.
+ if (Kind == k_IndirectRegDec)
+ OS << "-";
+
+ // Register or other symbol.
+ OS << StrFromLoc(this->getStartLoc(), this->getEndLoc());
+
+ // Indirect Post-Increment.
+ if (Kind == k_IndirectRegInc)
+ OS << "+";
}
};
@@ -297,14 +445,20 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
ParseStatus SuperHAsmParser::parseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
const AsmToken &Tok = Parser.getTok();
+ const MCExpr *Expr;
StartLoc = Tok.getLoc();
EndLoc = Tok.getEndLoc();
- if (Tok.is(AsmToken::Integer)) {
- Imm = Tok.getIntVal();
+ // Eat % and $ which are used in SuperH asm.
+ if (Tok.is(AsmToken::Percent) || Tok.is(AsmToken::Dollar))
Parser.Lex();
+
+ if (Parser.parseExpression(Expr, EndLoc))
+ return ParseStatus::Failure;
+
+ if (Expr->evaluateAsAbsolute(Imm))
return ParseStatus::Success;
- }
+
return ParseStatus::Failure;
}
@@ -326,9 +480,25 @@ ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
SMLoc StartLoc = getLexer().getLoc();
SMLoc EndLoc = getLexer().getLoc();
+
switch(Tok.getKind()) {
default: {
- return ParseStatus::Failure;
+
+ // Try parsing as register first.
+ unsigned RegKind;
+ MCRegister Reg;
+ if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+ Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
+ return ParseStatus::Success;
+ }
+
+ // That failed, try parsing as expression.
+ const MCExpr *EVal;
+ if (Parser.parseExpression(EVal, EndLoc))
+ return ParseStatus::Failure;
+
+ Operands.push_back(SuperHOperand::CreateFromExpr(EVal, StartLoc, EndLoc));
+ return ParseStatus::Success;
}
// Immediates.
@@ -346,14 +516,58 @@ ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
return ParseStatus::Failure;
}
- // Registers.
- case AsmToken::Identifier: {
- unsigned RegKind;
- MCRegister Reg;
- if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
- Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
- return ParseStatus::Success;
+ // Indirect Memory Access.
+ case AsmToken::At: {
+ Parser.Lex();
+
+ // Handle the different kinds of indirect memory access.
+ switch(Parser.getTok().getKind()) {
+ default: {
+ getLexer().UnLex(Tok);
+ return ParseStatus::Failure;
}
+
+ // Handle Register Indirect with Pre-Decrement.
+ case AsmToken::Minus: {
+ Parser.Lex();
+
+ unsigned RegKind;
+ MCRegister Reg;
+ if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+ Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
+ return ParseStatus::Success;
+ }
+
+ getLexer().UnLex(Tok);
+ return ParseStatus::Failure;
+ }
+
+ // Register Indirect
+ case AsmToken::Identifier: {
+
+ unsigned RegKind;
+ MCRegister Reg;
+ if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+
+ // Handle Register Indirect with Increment.
+ if (Parser.getTok().is(AsmToken::Plus)) {
+ Parser.Lex();
+
+ Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
+ return ParseStatus::Success;
+ }
+
+ Operands.push_back(SuperHOperand::CreateIReg(Reg, StartLoc, EndLoc));
+ return ParseStatus::Success;
+ }
+
+ getLexer().UnLex(Tok);
+ return ParseStatus::Failure;
+ }
+ }
+
+ // Un-lex on error
+ getLexer().UnLex(Tok);
return ParseStatus::Failure;
}
}
@@ -396,7 +610,23 @@ bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Nam
}
ParseStatus SuperHAsmParser::parseDirective(AsmToken DirectiveID) {
- return ParseStatus::NoMatch;
+ StringRef IDVal = DirectiveID.getIdentifier();
+ if (IDVal.starts_with(".gnu_attribute"))
+ parseGNUAttribute(DirectiveID.getLoc());
+ else
+ return ParseStatus::NoMatch;
+ return ParseStatus::Success;
+}
+
+bool SuperHAsmParser::parseGNUAttribute(SMLoc L) {
+ int64_t Tag;
+ int64_t IntegerValue;
+ if (!getParser().parseGNUAttribute(L, Tag, IntegerValue))
+ return false;
+
+ getParser().getStreamer().emitGNUAttribute(Tag, IntegerValue);
+
+ return true;
}
bool SuperHAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 9e30207f6b32c..2a1c28816c9a4 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -1,4 +1,4 @@
-//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
+//===-- SuperHAsmBackend.cpp - SuperH Assembler Backend ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,75 +6,175 @@
//
//===----------------------------------------------------------------------===//
-#include "MCTargetDesc/SuperHMCTargetDesc.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/MC/MCAsmBackend.h"
+#include "SuperHAsmBackend.h"
+#include "SuperHFixupKinds.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
-#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DebugLog.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-namespace {
-class SuperHAsmBackend : public MCAsmBackend {
-public:
- SuperHAsmBackend(const MCSubtargetInfo &STI)
- : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
+SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
? llvm::endianness::little
- : llvm::endianness::big) {}
+ : llvm::endianness::big),
+ STI(STI), OSABI(OSABI) {
- std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
- MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
- void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
- uint8_t *Data, uint64_t Value, bool IsResolved) override;
+}
- bool writeNopData(raw_ostream &OS, uint64_t Count,
- const MCSubtargetInfo *STI) const override {
+bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
+ const MCSubtargetInfo *STI) const {
- // If the count is not 4-byte aligned, we must be writing data into the
- // text section (otherwise we have unaligned instructions, and thus have
- // far bigger problems), so just write zeros instead.
- OS.write_zeros(Count % 2);
- return true;
+ // If the count is not 4-byte aligned, we must be writing data into the
+ // text section (otherwise we have unaligned instructions, and thus have
+ // far bigger problems), so just write zeros instead.
+ OS.write_zeros(Count % 2);
+ return true;
+}
+std::optional<MCFixupKind> SuperHAsmBackend::getFixupKind(StringRef Name) const {
+ if (STI.getTargetTriple().isOSBinFormatELF()) {
+ unsigned Type;
+ Type = llvm::StringSwitch<unsigned>(Name)
+#define ELF_RELOC(NAME, ID) .Case(#NAME, ID)
+#include "llvm/BinaryFormat/ELFRelocs/SuperH.def"
+#undef ELF_RELOC
+ .Default(-1u);
+ if (Type != -1u)
+ return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
}
-};
+ return std::nullopt;
+}
-class ELFSuperHAsmBackend : public SuperHAsmBackend {
- Triple::OSType OSType;
+MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
+ const static MCFixupKindInfo Infos[SuperH::NumTargetFixupKinds] = {
+ // This table *must* be in same the order of fixup_* kinds in
+ // AVRFixupKinds.h.
+ //
+ // name offset bits flags
+ {"fixup_12_pcrel", 12, 16, 0},
+ {"fixup_8_pcrel", 8, 16, 0},
+ {"fixup_4_pcrel", 4, 16, 0},
+ };
-public:
- ELFSuperHAsmBackend(const MCSubtargetInfo &STI, Triple::OSType OSType)
- : SuperHAsmBackend(STI), OSType(OSType) {}
+ if (mc::isRelocation(Kind))
+ return {};
- std::unique_ptr<MCObjectTargetWriter>
- createObjectTargetWriter() const override {
- uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
- return createSuperHELFObjectWriter(OSABI);
- }
-};
-} // end anonymous namespace
+ if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
-std::optional<MCFixupKind> SuperHAsmBackend::getFixupKind(StringRef Name) const {
- return std::nullopt;
-}
+ assert(unsigned(Kind - FirstTargetFixupKind) < SuperH::NumTargetFixupKinds &&
+ "Invalid kind!");
-MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
- return {"", 0, 2, 0};
+ return Infos[Kind - FirstTargetFixupKind];
}
void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target, uint8_t *Data,
uint64_t Value, bool IsResolved) {
+
+ // Handle Relocations
+ IsResolved = addReloc(F, Fixup, Target, Value, IsResolved);
+ MCFixupKind Kind = Fixup.getKind();
+ if (mc::isRelocation(Kind))
+ return;
+
+ // Handle non-relocations
+ MCContext &Ctx = getContext();
+ MCFixupKindInfo Info = getFixupKindInfo(Kind);
+ if (!Value)
+ return; // No encoding change.
+ unsigned NumBits = Info.TargetSize + Info.TargetOffset;
+ unsigned NumBytes = (NumBits / 8) + ((NumBits % 8) == 0 ? 0 : 1);
+
+ LDBG() << "Writing " << itostr(NumBytes) << " bytes, " << itostr(NumBits) << " bits.";
+ assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
+ "Invalid fixup offset!");
+
+ // Flip the bits if neccesary, then spit them out
+ Value <<= Info.TargetOffset;
+ bool SwapValue = Endian == llvm::endianness::big;
+ for (unsigned i = 0; i < NumBytes; ++i) {
+ unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
+ uint8_t mask = (((Value >> (i * 8)) & 0xff));
+ Data[Idx] |= mask;
+ }
+}
+
+bool SuperHAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t &FixedValue,
+ bool IsResolved) {
+
+ MCValue PCITarget; // PC-Indirect Target
+
+ // Get indirect target location.
+ switch(Fixup.getKind()) {
+ default:
+ return {};
+
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ case FK_Data_8: {
+ const auto *EValue = Fixup.getValue();
+ if (!EValue->evaluateAsRelocatable(PCITarget, Asm))
+ return true;
+ break;
+ }
+ }
+
+ // No target?
+ if (!PCITarget.getAddSym())
+ return false;
+
+ F.dump();
+
+ // Evaluate as ELF.
+ auto &SA = static_cast<const MCSymbolELF &>(*PCITarget.getAddSym());
+ if (SA.isUndefined())
+ return false;
+
+ // Check if resolvable.
+ IsResolved = &SA.getSection() == F.getParent() &&
+ SA.getBinding() == ELF::STB_LOCAL &&
+ SA.getType() != ELF::STT_GNU_IFUNC;
+ if (!IsResolved)
+ return false;
+
+ // Calculate fixed offset value.
+ // Note that the PC relative jumps are based on the start of the address.
+ // So it must be subtracted from the fixed value.
+ FixedValue = Asm->getSymbolOffset(SA) + PCITarget.getConstant();
+ FixedValue -= (Asm->getFragmentOffset(F) + Fixup.getOffset());
+ FixedValue /= 4; // Values are aligned to 4 bytes.
+ return true;
+}
+
+std::unique_ptr<MCObjectTargetWriter>
+SuperHAsmBackend::createObjectTargetWriter() const {
+ return createSuperHELFObjectWriter(OSABI);
}
MCAsmBackend *llvm::createSuperHAsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options) {
- return new ELFSuperHAsmBackend(STI, STI.getTargetTriple().getOS());
-}
+ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS());
+ return new SuperHAsmBackend(STI, OSABI);
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
new file mode 100644
index 0000000000000..f0e7e969f2d35
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
@@ -0,0 +1,48 @@
+//===-- SuperHAsmBackend.h - SuperH Assembler Backend ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHASMBACKEND_H
+#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHASMBACKEND_H
+
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "MCTargetDesc/SuperHMCAsmInfo.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+
+
+namespace llvm {
+class MCAssembler;
+class MCObjectTargetWriter;
+class raw_ostream;
+
+class SuperHAsmBackend : public MCAsmBackend {
+protected:
+ const MCSubtargetInfo &STI;
+ uint8_t OSABI;
+public:
+ SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI);
+ ~SuperHAsmBackend() override = default;
+
+ std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
+ MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
+ void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
+ uint8_t *Data, uint64_t Value, bool IsResolved) override;
+ bool addReloc(const MCFragment &F, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t &FixedValue,
+ bool IsResolved);
+
+ std::unique_ptr<MCObjectTargetWriter>
+ createObjectTargetWriter() const override;
+
+ bool writeNopData(raw_ostream &OS, uint64_t Count,
+ const MCSubtargetInfo *STI) const override;
+};
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index 8df58460dc2a9..d74ebf2a297e5 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -18,7 +18,7 @@
using namespace llvm;
-namespace {
+namespace llvm {
class SuperHELFObjectWriter : public MCELFObjectTargetWriter {
public:
SuperHELFObjectWriter(uint8_t OSABI)
@@ -33,7 +33,7 @@ namespace {
unsigned getRelocType(const MCFixup &Fixup, const MCValue &Target,
bool IsPCRel) const override;
- bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;
+ bool needsRelocateWithSymbol(const MCValue &Val, unsigned Type) const override;
};
}
@@ -43,9 +43,8 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
return ELF::R_SH_NONE;
}
-bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
+bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
unsigned Type) const {
-
return false;
}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
new file mode 100644
index 0000000000000..0214153296167
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
@@ -0,0 +1,46 @@
+//===-- SuperHFixupKinds.h - AVR Specific Fixup Entries ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPERH_FIXUP_KINDS_H
+#define LLVM_SUPERH_FIXUP_KINDS_H
+
+#include "llvm/MC/MCFixup.h"
+
+namespace llvm {
+namespace SuperH {
+
+/// The set of supported fixups.
+///
+/// Although most of the current fixup types reflect a unique relocation
+/// one can have multiple fixup types for a given relocation and thus need
+/// to be uniquely named.
+///
+/// \note This table *must* be in the same order of
+/// MCFixupKindInfo Infos[AVR::NumTargetFixupKinds]
+/// in `AVRAsmBackend.cpp`.
+enum Fixups {
+
+ // Fixup which uses 12 bits and is PC relative.
+ // Used in specific displacement operands.
+ fixup_12_pcrel = FirstTargetFixupKind,
+
+ // Fixup which uses 8 bits and is PC relative.
+ fixup_8_pcrel,
+
+ // Fixup which uses 4 bits and is PC relative.
+ fixup_4_pcrel,
+
+ // Marker
+ LastTargetFixupKind,
+ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
+};
+
+} // namespace SuperH
+} // namespace llvm
+
+#endif // LLVM_SUPERH_FIXUP_KINDS_H
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
index a98647bc36f26..7596ece4b12ec 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -24,4 +24,6 @@ SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
this->IsLittleEndian = TheTriple.isLittleEndian();
this->CommentString = ";";
this->SeparatorString = "\n";
+ this->InternalSymbolPrefix = ".L";
+ this->PrivateLabelPrefix = ".L";
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 380247543dff6..d4d546ef0e443 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -28,6 +28,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/EndianStream.h"
+#include <cstdint>
using namespace llvm;
@@ -63,6 +64,10 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+
+ unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
};
} // end namespace
@@ -83,6 +88,31 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
++MCNumEmitted;
}
+unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ MCExpr::ExprKind Kind = Expr->getKind();
+
+ // Binary Op
+ if (Kind == MCExpr::Binary) {
+ Expr = static_cast<const MCBinaryExpr *>(Expr)->getLHS();
+ Kind = Expr->getKind();
+ }
+
+ // Symbol Reference
+ if (Kind == MCExpr::SymbolRef) {
+ Fixups.push_back(MCFixup::create(0, Expr, FK_Data_2, true));
+ return 0;
+ }
+
+ // Constant immediate.
+ int64_t Result;
+ if (Expr->evaluateAsAbsolute(Result))
+ return Result;
+
+ return 0;
+}
+
unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
@@ -92,7 +122,8 @@ unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperan
if (MO.isImm())
return MO.getImm();
- return 0;
+ assert(MO.isExpr() && "Expected Expression");
+ return getExprOpValue(MI, MO.getExpr(), Fixups, STI);
}
MCCodeEmitter *llvm::createSuperHMCCodeEmitter(const MCInstrInfo &MCII,
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index a035fbdaff85d..75c2112f854e7 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -131,7 +131,8 @@ def SuperHAsmParser : AsmParser {
def SuperHAsmParserVariant : AsmParserVariant {
let Variant = 0;
let Name = "Hitachi";
- let TokenizingCharacters = "[]*!#";
+ let SeparatorCharacters = " \t,";
+ let TokenizingCharacters = "()[]*!#@-+";
let CommentDelimiter = ";";
}
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
new file mode 100644
index 0000000000000..ba6ac8c025335
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -0,0 +1,60 @@
+//===-- SuperHCallingConv.td - Calling Conventions for SuperH -*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-------------------------------------------------------------------------===//
+// This describes the calling conventions for the SuperH architecture.
+//===-------------------------------------------------------------------------===//
+
+//===-------------------------------------------------------------------------===//
+// SuperH CDECL Calling Convention
+//===-------------------------------------------------------------------------===//
+let Entry = 1 in
+def CC_SH_CDECL : CallingConv<[
+
+ // Handles byval parameters.
+ CCIfByVal<CCPassByVal<4, 4>>,
+ CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+
+ CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
+ CCIfType<[i32], CCAssignToStack<4, 4>>,
+ CCIfType<[f32], CCAssignToStack<4, 4>>,
+]>;
+
+def CC_SH_RENESAS : CallingConv<[
+
+ // Handles byval parameters.
+ CCIfByVal<CCPassByVal<4, 4>>,
+ CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+
+ CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
+ CCIfType<[i32], CCAssignToStack<4, 4>>,
+ CCIfType<[f32], CCAssignToStack<4, 4>>,
+]>;
+
+def CC_SH_WinCE : CallingConv<[
+
+ // Handles byval parameters.
+ CCIfByVal<CCPassByVal<4, 4>>,
+ CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+
+ CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
+ CCIfType<[i32], CCAssignToStack<4, 4>>,
+ CCIfType<[f32], CCAssignToStack<4, 4>>,
+]>;
+
+//===----------------------------------------------------------------------===//
+// Callee-saved register lists.
+//===----------------------------------------------------------------------===//
+
+def CSR_SH_CDECL : CalleeSavedRegs<(add R8, R9, R10, R11, R12,
+ R13, R14, R15)>;
+
+def CSR_SH_RENESAS : CalleeSavedRegs<(add R4, R5, R6, R7, R8,
+ R9, R10, R11, R12, R13,
+ R14, R15)>;
+
+def CSR_SH_WINCE : CalleeSavedRegs<(add R8, R9, R10, R11, R12,
+ R13, R14, R15)>;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td b/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
index 8b4add0af3314..d16a588da07a0 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
@@ -13,17 +13,65 @@
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
-// Instructions
+// Arithmetic Instructions
//===----------------------------------------------------------------------===//
let Namespace = "SH" in {
- def ADD_ir : Op_ir<0b0011100000000000, "add">;
- def ADD_rr : Op_rr<0b0011000000001100, "add">;
- def ADDC_rr : Op_rr<0b0011000000001110, "addc">;
- def ADDV_rr : Op_rr<0b0011000000001111, "addv">;
- def DIV0S_rr : Op_rr<0b0010000000000111, "div0s">;
- def DIV0U_rr : Op<0b0000000000011001, "div0u">;
- def DIV1_rr : Op_rr<0b0011000000000100, "div1">;
- def DIVS_rr0 : Op_rr0<0b0100000010010100, "divs">;
- def DIVU_rr0 : Op_rr0<0b0100000010000100, "divu">;
+
+ // ADDITION
+ def ADD_Rm_Rn : Op_Rm_Rn<0b0011000000001100, "add">;
+ def ADD_imm_Rn : Op_Imm_Rn<0b0111000000000000, "add">;
+ def ADDC_Rm_Rn : Op_Rm_Rn<0b0011000000001110, "addc">;
+ def ADDV_Rm_Rn : Op_Rm_Rn<0b0011000000001111, "addv">;
+
+ // SUBTRACTION
+ def DT_Rn : Op_Rn<0b0100000000010000, "dt">;
+ def NEG_Rm_Rn : Op_Rm_Rn<0b0110000000001011, "neg">;
+ def NEGC_Rm_Rn : Op_Rm_Rn<0b0110000000001010, "negc">;
+ def SUB_Rm_Rn : Op_Rm_Rn<0b0011000000001000, "sub">;
+ def SUBC_Rm_Rn : Op_Rm_Rn<0b0011000000001010, "subc">;
+ def SUBV_Rm_Rn : Op_Rm_Rn<0b0011000000001011, "subv">;
+
+ // MULTIPLICATION
+ def MUL_Rm_Rn : Op_Rm_Rn<0b0000000000000111, "mul.l">;
+ def MULR_R0_Rn : Op_Rm_Rn<0b0100000010000000, "mulr">;
+ def MULSW_Rm_Rn : Op_Rm_Rn<0b0010000000001111, "muls.w">;
+ def MULUW_Rm_Rn : Op_Rm_Rn<0b0010000000001110, "mulu.w">;
+ def DMULS_Rm_Rn : Op_Rm_Rn<0b0011000000001101, "dmuls.l">;
+ def DMULU_Rm_Rn : Op_Rm_Rn<0b0011000000000101, "dmulu.l">;
+
+ // DIVISION
+ def DIV0S_Rm_Rn : Op_Rm_Rn<0b0010000000000111, "div0s">;
+ def DIV0U : Op<0b0000000000011001, "div0u">;
+ def DIV1_Rm_Rn : Op_Rm_Rn<0b0011000000000100, "div1">;
+ def DIVS_R0_Rn : Op_R0_Rn<0b0100000010010100, "divs">;
+ def DIVU_R0_Rn : Op_R0_Rn<0b0100000010000100, "divu">;
+
+ // COMPARISON
+ def CMPEQ_Imm_R0 : Op_Imm_R0<0b1000100000000000, "cmp/eq">;
+ def CMPEQ_Rm_Rn : Op_Rm_Rn<0b0011000000000000, "cmp/eq">;
+ def CMPHS_Rm_Rn : Op_Rm_Rn<0b0011000000000010, "cmp/hs">;
+ def CMPGE_Rm_Rn : Op_Rm_Rn<0b0011000000000011, "cmp/ge">;
+ def CMPHI_Rm_Rn : Op_Rm_Rn<0b0011000000000110, "cmp/hi">;
+ def CMPGT_Rn : Op_Rn<0b0011000000000111, "cmp/gt">;
+ def CMPPL_Rn : Op_Rn<0b0100000000010101, "cmp/pl">;
+ def CMPPZ_Rn : Op_Rn<0b0100000000010001, "cmp/pz">;
+ def CMPSTR_Rm_Rn : Op_Rm_Rn<0b0010000000001100, "cmp/str">;
+
+ // INTEGER EXTENSION
+ def EXTSB_Rm_Rn : Op_Rm_Rn<0b0110000000001110, "exts.b">;
+ def EXTSW_Rm_Rn : Op_Rm_Rn<0b0110000000001111, "exts.w">;
+ def EXTUB_Rm_Rn : Op_Rm_Rn<0b0110000000001100, "extu.b">;
+ def EXTUW_Rm_Rn : Op_Rm_Rn<0b0110000000001101, "extu.w">;
+
+ // LOGIC
+ def AND_Rm_Rn : Op_Rm_Rn<0b0010000000001001, "and">;
+ def AND_Imm_R0 : Op_Imm_R0<0b1100100100000000, "and">;
+ def NOT_Rm_Rn : Op_Rm_Rn<0b0110000000000111, "not">;
+ def OR_Rm_Rn : Op_Rm_Rn<0b0010000000001011, "or">;
+ def OR_Imm_R0 : Op_Imm_R0<0b1100101100000000, "or">;
+ def TST_Rm_Rn : Op_Rm_Rn<0b0010000000001000, "tst">;
+ def TST_Imm_R0 : Op_Imm_R0<0b1100100000000000, "tst">;
+ def XOR_Rm_Rn : Op_Rm_Rn<0b0010000000001010, "xor">;
+ def XOR_Imm_R0 : Op_Imm_R0<0b1100101000000000, "xor">;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrBranch.td b/llvm/lib/Target/SuperH/SuperHInstrBranch.td
new file mode 100644
index 0000000000000..939dfc2ec6256
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrBranch.td
@@ -0,0 +1,76 @@
+//===-- SuperHInstrBranch.td - SuperH Branching Instructions -*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-----------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes all of the arithmetic instructions in the SuperH
+/// ISA.
+///
+//===-----------------------------------------------------------------------===//
+
+//===-----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===-----------------------------------------------------------------------===//
+
+
+// disp + PC -> PC
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true in
+class BrOp_Disp8<bits<16> op, string opcodestr>
+ : SHInstOP_D8<op, (outs), (ins disp8:$disp),
+ !strconcat(opcodestr, " $disp")>;
+// disp + PC -> PC
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true in
+class BrOp_Disp12<bits<16> op, string opcodestr>
+ : SHInstOP_D12<op, (outs), (ins disp12:$disp),
+ !strconcat(opcodestr, " $disp")>;
+
+// disp + PC -> PC (Delayed)
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true, hasDelaySlot = true in
+class BrOpD_Disp8<bits<16> op, string opcodestr>
+ : SHInstOP_D8<op, (outs), (ins disp8:$disp),
+ !strconcat(opcodestr, " $disp")>;
+
+// Rm + PC -> PC
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true, isIndirectBranch = true in
+class BrOp_Rm<bits<16> op, string opcodestr>
+ : SHInstOP_M4<op, (outs), (ins GPR:$Rm),
+ !strconcat(opcodestr, " $Rm")>;
+// Rm -> PC
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true, isIndirectBranch = true in
+class BrOp_Rmi<bits<16> op, string opcodestr>
+ : SHInstOP_M4<op, (outs), (ins GPRMem:$Rm),
+ !strconcat(opcodestr, " @$Rm")>;
+
+// CALL
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = true in
+class BrOpCall_Rmi<bits<16> op, string opcodestr>
+ : SHInstOP_M4<op, (outs), (ins GPRMem:$Rm),
+ !strconcat(opcodestr, " @$Rm")>;
+
+// RETURN
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isReturn = true in
+class BrOpRet<bits<16> op, string opcodestr>
+ : SHInstOP<op, (outs), (ins), opcodestr>;
+
+
+//===-----------------------------------------------------------------------===//
+// Branch Instructions
+//===-----------------------------------------------------------------------===//
+
+let Namespace = "SH" in {
+ def BF_Disp : BrOp_Disp8<0b1000101100000000, "bf">;
+ def BFS_Disp : BrOpD_Disp8<0b1000111100000000, "bf/s">;
+ def BT_Disp : BrOp_Disp8<0b1000100100000000, "bt">;
+ def BTS_Disp : BrOpD_Disp8<0b1000110100000000, "bt/s">;
+ def BRA_Disp : BrOp_Disp12<0b1010000000000000, "bra">;
+ def BRAF_Rm : BrOp_Rm<0b0000000000100011, "braf">;
+ def BSR_Disp : BrOp_Disp12<0b1011000000000000, "bsr">;
+ def BSRF_Rm : BrOp_Rm<0b0000000000000011, "bsrf">;
+ def JMP_Rmi : BrOp_Rmi<0b0100000000101011, "jmp">;
+ def JSR_Rmi : BrOpCall_Rmi<0b0100000000001011, "jsr">;
+ def RTS : BrOpRet<0b0000000000001011, "rts">;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrData.td b/llvm/lib/Target/SuperH/SuperHInstrData.td
index 983f0ba58024a..97257cff43d88 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrData.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrData.td
@@ -12,6 +12,103 @@
///
//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+
+// LOAD
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
+
+ // X -> Rn
+ class LdOp_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4<op, (outs GPR:$Rn), (ins),
+ !strconcat(opcodestr, " $Rn")>;
+
+ // Rm -> Rn
+ class LdOp_Rm_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
+ !strconcat(opcodestr, " $Rm, $Rn")>;
+
+ // #imm -> sign extension -> Rn
+ class LdOp_Imm_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_I8<op, (outs GPR:$Rn), (ins imm8:$imm),
+ !strconcat(opcodestr, " $imm, $Rn")>;
+
+ // (disp) -> R0
+ class LdOp_DispPC_R0<bits<16> op, string opcodestr>
+ : SHInstOP_D8<op, (outs), (ins disp8:$disp),
+ !strconcat(opcodestr, " @($disp,pc),R0")>;
+
+ // (disp) -> [sign extension] -> Rn
+ class LdOp_DispPC_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_D8<op, (outs GPR:$Rn), (ins disp8:$disp),
+ !strconcat(opcodestr, " @($disp,pc), $Rn")>;
+
+ // (Rm) -> [sign extension] -> Rn
+ class LdOp_Rmi_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPRMem:$Rm),
+ !strconcat(opcodestr, " @$Rm, $Rn")>;
+
+ // (Rm) -> [sign extension] -> Rn, Rm+1 -> Rm
+ class LdOp_Rminci_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPRMem:$Rm),
+ !strconcat(opcodestr, " @$Rm+, $Rn")>;
+
+ // (disp + Rm) -> [sign extension] -> R0
+ class LdOp_DispRm_R0<bits<16> op, string opcodestr>
+ : SHInstOP_M4_D4<op, (outs), (ins disp4:$disp, GPR:$Rm),
+ !strconcat(opcodestr, " @($disp, $Rm), R0")>;
+
+ // (disp + Rm) -> [sign extension] -> Rn
+ class LdOp_DispRm_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4_D4<op, (outs GPR:$Rn), (ins disp4:$disp, GPR:$Rm),
+ !strconcat(opcodestr, " @($disp, $Rm), $Rn")>;
+
+ // (R0 + Rm) -> [sign extension] -> Rn
+ class LdOp_RelR0Rm_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
+ !strconcat(opcodestr, " @(R0, $Rm), $Rn")>;
+
+ // (disp + GBR) -> [sign extension] -> R0
+ class LdOp_DispGBR_R0<bits<16> op, string opcodestr>
+ : SHInstOP_D8<op, (outs), (ins disp8:$disp),
+ !strconcat(opcodestr, " @($disp, gbr),R0")>;
+}
+
+// STORE
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
+
+
+ // Rm -> [sign extension] -> (Rn)
+ class StOp_Rm_Rni<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
+ !strconcat(opcodestr, " $Rm, @$Rn")>;
+
+ // Rn-1 -> Rn, Rm -> [sign extension] -> (Rn)
+ class StOp_Rm_Rndeci<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPRMem:$Rn), (ins GPR:$Rm),
+ !strconcat(opcodestr, " $Rm, @-$Rn")>;
+
+ // R0 -> [sign extension] -> (disp + Rn)
+ class StOp_R0_DispRn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_D4<op, (outs disp4:$disp, GPR:$Rn), (ins),
+ !strconcat(opcodestr, " R0, @( $disp, $Rn )")>;
+
+ // Rm -> [sign extension] -> (disp + Rn)
+ class StOp_Rm_DispRn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4_D4<op, (outs disp4:$disp, GPR:$Rn), (ins GPR:$Rm),
+ !strconcat(opcodestr, " $Rm, @( $disp, $Rn )")>;
+
+ // Rm -> (R0 + Rn)
+ class StOp_Rm_RelR0Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
+ !strconcat(opcodestr, " $Rm, @(R0, $Rn)")>;
+
+ // R0 -> (disp + GBR)
+ class StOp_R0_DispGBR<bits<16> op, string opcodestr>
+ : SHInstOP_D8<op, (outs disp8:$disp), (ins),
+ !strconcat(opcodestr, " R0, @($disp, gbr)")>;
+}
//===----------------------------------------------------------------------===//
@@ -19,12 +116,57 @@
//===----------------------------------------------------------------------===//
let Namespace = "SH" in {
- def MOV_ir : Op_ir<0b1110000000000000, "mov">;
- def MOV_rr : Op_rr<0b0110000000000011, "mov">;
- def MOVB_rri : Store_rr<0b0010000000000000, "mov.b">;
- def MOVW_rri : Store_rr<0b0010000000000001, "mov.w">;
- def MOVL_rri : Store_rr<0b0010000000000010, "mov.l">;
- def MOVB_rir : Load_rr<0b0110000000000000, "mov.b">;
- def MOVW_rir : Load_rr<0b0110000000000001, "mov.w">;
- def MOVL_rir : Load_rr<0b0110000000000010, "mov.l">;
-}
\ No newline at end of file
+
+ // LOADS
+ def MOV_Rm_Rn : LdOp_Rm_Rn<0b0110000000000011, "mov">;
+ def MOVA_dispPC_R0 : LdOp_DispPC_R0<0b1100011100000000, "mova">;
+ def MOVW_dispPC_Rn : LdOp_DispPC_Rn<0b1001000000000000, "mov.w">;
+ def MOVL_dispPC_Rn : LdOp_DispPC_Rn<0b1101000000000000, "mov.l">;
+ def MOVB_Rmi_Rn : LdOp_Rmi_Rn<0b0110000000000000, "mov.b">;
+ def MOVW_Rmi_Rn : LdOp_Rmi_Rn<0b0110000000000001, "mov.w">;
+ def MOVL_Rmi_Rn : LdOp_Rmi_Rn<0b0110000000000010, "mov.l">;
+ def MOVB_Rminci_Rn : LdOp_Rminci_Rn<0b0110000000000100, "mov.b">;
+ def MOVW_Rminci_Rn : LdOp_Rminci_Rn<0b0110000000000101, "mov.w">;
+ def MOVL_Rminci_Rn : LdOp_Rminci_Rn<0b0110000000000110, "mov.l">;
+ def MOVB_dispRm_R0 : LdOp_DispRm_R0<0b1000010000000000, "mov.b">;
+ def MOVW_dispRm_R0 : LdOp_DispRm_R0<0b1000010100000000, "mov.w">;
+ def MOVL_dispRm_Rn : LdOp_DispRm_Rn<0b0101000000000000, "mov.l">;
+ def MOVB_RelR0Rm_Rn : LdOp_RelR0Rm_Rn<0b0000000000001100, "mov.b">;
+ def MOVW_RelR0Rm_Rn : LdOp_RelR0Rm_Rn<0b0000000000001101, "mov.w">;
+ def MOVL_RelR0Rm_Rn : LdOp_RelR0Rm_Rn<0b0000000000001110, "mov.l">;
+ def MOVB_dispGBR_R0 : LdOp_DispGBR_R0<0b1100010000000000, "mov.b">;
+ def MOVW_dispGBR_R0 : LdOp_DispGBR_R0<0b1100010100000000, "mov.w">;
+ def MOVL_dispGBR_R0 : LdOp_DispGBR_R0<0b1100011000000000, "mov.l">;
+
+ def MOVRT_Rn : LdOp_Rn<0b0000000000111001, "movrt">;
+ def MOVT_Rn : LdOp_Rn<0b0000000000101001, "movt">;
+
+ // STORES
+ def MOV_imm_Rn : LdOp_Imm_Rn<0b1110000000000000, "mov">;
+ def MOVB_Rm_Rni : StOp_Rm_Rni<0b0010000000000000, "mov.b">;
+ def MOVW_Rm_Rni : StOp_Rm_Rni<0b0010000000000001, "mov.w">;
+ def MOVL_Rm_Rni : StOp_Rm_Rni<0b0010000000000010, "mov.l">;
+ def MOVB_Rm_Rndeci : StOp_Rm_Rndeci<0b0010000000000100, "mov.b">;
+ def MOVW_Rm_Rndeci : StOp_Rm_Rndeci<0b0010000000000101, "mov.w">;
+ def MOVL_Rm_Rndeci : StOp_Rm_Rndeci<0b0010000000000110, "mov.l">;
+ def MOVB_R0_dispRn : StOp_R0_DispRn<0b1000000000000000, "mov.b">;
+ def MOVW_R0_dispRn : StOp_R0_DispRn<0b1000000100000000, "mov.w">;
+ def MOVL_Rm_dispRn : StOp_Rm_DispRn<0b0001000000000000, "mov.l">;
+ def MOVB_Rm_RelR0Rn : StOp_Rm_RelR0Rn<0b0000000000000100, "mov.b">;
+ def MOVW_Rm_RelR0Rn : StOp_Rm_RelR0Rn<0b0000000000000101, "mov.w">;
+ def MOVL_Rm_RelR0Rn : StOp_Rm_RelR0Rn<0b0000000000000110, "mov.l">;
+ def MOVB_R0_dispGBR : StOp_R0_DispGBR<0b1100000000000000, "mov.b">;
+ def MOVW_R0_dispGBR : StOp_R0_DispGBR<0b1100000100000000, "mov.w">;
+ def MOVL_R0_dispGBR : StOp_R0_DispGBR<0b1100001000000000, "mov.l">;
+
+ // OTHER
+ def NOTT : Op<0b0000000001101000, "nott">;
+ def SWAPB_Rm_Rn : Op_Rm_Rn<0b0110000000001000, "swap.b">;
+ def SWAPW_Rm_Rn : Op_Rm_Rn<0b0110000000001001, "swap.w">;
+ def XTRCT_Rm_Rn : Op_Rm_Rn<0b0010000000001101, "xtrct">;
+}
+
+// LOAD ALIASES
+def MOVA_Disp_R0 : InstAlias<"mova $disp, R0", (MOVA_dispPC_R0 disp8:$disp), 0>;
+def MOVW_Disp_Rn : InstAlias<"mov.w $disp, $Rn", (MOVW_dispPC_Rn GPR:$Rn, disp8:$disp), 0>;
+def MOVL_Disp_Rn : InstAlias<"mov.l $disp, $Rn", (MOVL_dispPC_Rn GPR:$Rn, disp8:$disp), 0>;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index af2f4d4a8f394..dbe83b764fbee 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -25,6 +25,7 @@
// * 00000000mmmmdddd (OP, Rm, disp) OP_M4_D4
// * 0000nnnnmmmmdddd (OP, Rn, Rm, disp) OP_N4_M4_D4
// * 00000000dddddddd (OP, disp) OP_D8
+// * 0000dddddddddddd (OP, disp) OP_D12
// * 00000000iiiiiiii (OP, imm) OP_I8
// * 0000nnnn00000000 (OP, Rn, OP) OP_N4
// * 0000mmmm00000000 (OP, Rm, OP) OP_M4
@@ -71,9 +72,9 @@ class SHInstOP_N4_I8 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{15-12} = Opcode{15-12};
// Operands
- bits<4> n;
+ bits<4> Rn;
bits<8> imm;
- let Inst{11-8} = n;
+ let Inst{11-8} = Rn;
let Inst{7-0} = imm;
}
@@ -86,9 +87,9 @@ class SHInstOP_N4_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{15-12} = Opcode{15-12};
// Operands
- bits<4> n;
+ bits<4> Rn;
bits<8> disp;
- let Inst{11-8} = n;
+ let Inst{11-8} = Rn;
let Inst{7-0} = disp;
}
@@ -101,10 +102,10 @@ class SHInstOP_N4_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{3-0} = Opcode{3-0};
// Operands
- bits<4> n;
- bits<4> m;
- let Inst{11-8} = n;
- let Inst{7-4} = m;
+ bits<4> Rn;
+ bits<4> Rm;
+ let Inst{11-8} = Rn;
+ let Inst{7-4} = Rm;
}
class SHInstOP_N4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -115,10 +116,10 @@ class SHInstOP_N4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{15-8} = Opcode{15-8};
// Operands
- bits<4> n;
+ bits<4> Rn;
bits<4> disp;
- let Inst{11-8} = disp;
- let Inst{15-12} = n;
+ let Inst{7-4} = Rn;
+ let Inst{0-3} = disp;
}
class SHInstOP_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -129,10 +130,10 @@ class SHInstOP_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{15-8} = Opcode{15-8};
// Operands
- bits<4> m;
+ bits<4> Rm;
bits<4> disp;
- let Inst{11-8} = disp;
- let Inst{15-12} = m;
+ let Inst{7-4} = Rm;
+ let Inst{0-3} = disp;
}
class SHInstOP_N4_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -143,14 +144,26 @@ class SHInstOP_N4_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{15-12} = Opcode{15-12};
// Operands
- bits<4> n;
- bits<4> m;
+ bits<4> Rn;
+ bits<4> Rm;
bits<4> disp;
- let Inst{11-8} = n;
- let Inst{7-4} = m;
+ let Inst{11-8} = Rn;
+ let Inst{7-4} = Rm;
let Inst{0-3} = disp;
}
+class SHInstOP_D12 <bits<16> opcode, dag outs, dag ins, string asmstr>
+ : SHInst<outs, ins, asmstr, []> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{15-12} = Opcode{15-12};
+
+ // Operands
+ bits<12> disp;
+ let Inst{11-0} = disp;
+}
+
class SHInstOP_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
: SHInst<outs, ins, asmstr, []> {
@@ -184,8 +197,8 @@ class SHInstOP_N4 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{7-0} = Opcode{7-0};
// Operands
- bits<4> n;
- let Inst{11-8} = n;
+ bits<4> Rn;
+ let Inst{11-8} = Rn;
}
class SHInstOP_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
@@ -197,8 +210,8 @@ class SHInstOP_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{7-0} = Opcode{7-0};
// Operands
- bits<4> m;
- let Inst{11-8} = m;
+ bits<4> Rm;
+ let Inst{11-8} = Rm;
}
class SHInstOP <bits<16> opcode, dag outs, dag ins, string asmstr>
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 13761e4447da0..9209450d1a196 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -65,78 +65,123 @@ def SHRet : SDNode<"SHISD::RET", SHSDT_Ret,
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
//===----------------------------------------------------------------------===//
-// Operands
+// Operand Classes
//===----------------------------------------------------------------------===//
-class ImmAsmOperand<int width> : AsmOperandClass {
- let Name = "Imm" # width;
+// Base Operand Class
+class SHOpClass<string name,
+ list<AsmOperandClass> superClasses = []> : AsmOperandClass {
+ let Name = name;
+ let ParserMethod = "parseOperand";
+ let SuperClasses = superClasses;
+}
+
+// Immediates
+class SHImmClass<int width> : SHOpClass<"Imm" # width> {
+ let PredicateMethod = "isImm";
let RenderMethod = "addImmOperands";
}
-def imm8 : Operand<i8>, ImmLeaf<i32, [{return isInt<8>(Imm);}]> {
- let ParserMatchClass = ImmAsmOperand<8>;
+// Displacements
+class SHDispClass<int width> : SHOpClass<"Disp" # width> {
+ let PredicateMethod = "isDisp";
+ let RenderMethod = "addDispOperands";
+}
+
+// Memory Ops
+class SHMemClass : SHOpClass<"Mem"> {
+ let PredicateMethod = "isMem";
+ let RenderMethod = "addMemOperands";
+}
+
+//===----------------------------------------------------------------------===//
+// Operands
+//===----------------------------------------------------------------------===//
+
+// Immediate
+class SHImmOp<int width, ValueType vt>
+ : Operand<vt> {
+ let ParserMatchClass = SHImmClass<width>;
+ let OperandType = "OPERAND_IMMEDIATE";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isInt<#width>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+
+def imm8 : SHImmOp<8, i8>;
+
+// Displacement
+class SHDispOp<int width, ValueType vt>
+ : Operand<vt> {
+ let ParserMatchClass = SHDispClass<width>;
+ let OperandType = "OPERAND_IMMEDIATE";
let MCOperandPredicate = [{
int64_t Imm;
if (MCOp.evaluateAsConstantImm(Imm))
- return isInt<8>(Imm);
+ return isInt<#width>(Imm);
return MCOp.isBareSymbolRef();
}];
}
+def disp4 : SHDispOp<4, i4>;
+def disp8 : SHDispOp<8, i8>;
+def disp12 : SHDispOp<12, i16>;
+
+
+
+// Memory
+class SHMemRegOp<RegisterClass regClass>
+ : RegisterOperand<regClass> {
+ let ParserMatchClass = SHMemClass<>;
+ let OperandType = "OPERAND_MEMORY";
+}
+def GPRMem : SHMemRegOp<GPR>;
//===----------------------------------------------------------------------===//
// Instruction Class Templates
//===----------------------------------------------------------------------===//
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
// No-arg instruction
class Op<bits<16> op, string opcodestr>
: SHInstOP<op, (outs), (ins), opcodestr>;
// Rn
- class Op_r<bits<16> op, string opcodestr>
- : SHInstOP_N4<op, (outs GPR:$n), (ins),
- !strconcat(opcodestr, " $n")>;
-
- // R0, Rn
- class Op_rr0<bits<16> op, string opcodestr>
- : SHInstOP_N4<op, (outs GPR:$n), (ins),
- !strconcat(opcodestr, " r0, $n")>;
-
- // imm -> Sign Extension -> Rn
- class Op_ir<bits<16> op, string opcodestr>
- : SHInstOP_N4_I8<op, (outs GPR:$n), (ins imm8:$imm),
- !strconcat(opcodestr, " $imm, $n")>;
-
- // Rm -> Rn
- class Op_rr<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
- !strconcat(opcodestr, " $m, $n")>;
+ class Op_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4<op, (outs GPR:$Rn), (ins),
+ !strconcat(opcodestr, " $Rn")>;
+
+ // R0 -> (OP) -> Rn
+ class Op_R0_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4<op, (outs GPR:$Rn), (ins),
+ !strconcat(opcodestr, " r0,$Rn")>;
+
+ // Rm -> (OP) -> Rn
+ class Op_Rm_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
+ !strconcat(opcodestr, " $Rm,$Rn")>;
+
+ // imm -> (OP) -> Rn
+ class Op_Imm_Rn<bits<16> op, string opcodestr>
+ : SHInstOP_N4_I8<op, (outs GPR:$Rn), (ins imm8:$imm),
+ !strconcat(opcodestr, " $imm,$Rn")>;
+
+ // imm -> (OP) -> Rn
+ class Op_Imm_R0<bits<16> op, string opcodestr>
+ : SHInstOP_I8<op, (outs), (ins imm8:$imm),
+ !strconcat(opcodestr, " $imm,R0")>;
}
-let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
-
- // Rm -> (Rn)
- class Store_rr<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
- !strconcat(opcodestr, " $m, $n")>;
-}
-
-let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
-
- // (Rm) -> Sign Extension -> Rn
- class Load_rr<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$n), (ins GPR:$m),
- !strconcat(opcodestr, " $m, $n")>;
-}
//===----------------------------------------------------------------------===//
// Basic Instructions
//===----------------------------------------------------------------------===//
// NOP instruction, does nothing.
-def NOP : Op<0b0000000000000000, "nop">;
-def RTS : Op<0b0000000000001011, "rts">;
+def NOP : Op<0b0000000000001001, "nop">;
//===----------------------------------------------------------------------===//
// Subsystems
@@ -144,6 +189,7 @@ def RTS : Op<0b0000000000001011, "rts">;
include "SuperHInstrData.td"
include "SuperHInstrArithmetic.td"
+include "SuperHInstrBranch.td"
//===----------------------------------------------------------------------===//
// Pseudo instructions
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index fc4c05dadb994..a1594fb811b08 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -84,45 +84,45 @@ class MTRXReg<bits<16> Enc, string n> : SHReg<Enc, n>;
let Namespace = "SH" in {
// General Purpose Registers
- def R0 : GPRReg<0, "r0">, DwarfRegNum<[0]>;
- def R1 : GPRReg<1, "r1">, DwarfRegNum<[1]>;
- def R2 : GPRReg<2, "r2">, DwarfRegNum<[2]>;
- def R3 : GPRReg<3, "r3">, DwarfRegNum<[3]>;
- def R4 : GPRReg<4, "r4">, DwarfRegNum<[4]>;
- def R5 : GPRReg<5, "r5">, DwarfRegNum<[5]>;
- def R6 : GPRReg<6, "r6">, DwarfRegNum<[6]>;
- def R7 : GPRReg<7, "r7">, DwarfRegNum<[7]>;
- def R8 : GPRReg<8, "r8">, DwarfRegNum<[8]>;
- def R9 : GPRReg<9, "r9">, DwarfRegNum<[9]>;
- def R10 : GPRReg<10, "r10">, DwarfRegNum<[10]>;
- def R11 : GPRReg<11, "r11">, DwarfRegNum<[11]>;
- def R12 : GPRReg<12, "r12">, DwarfRegNum<[12]>;
- def R13 : GPRReg<13, "r13">, DwarfRegNum<[13]>;
- def R14 : GPRReg<14, "r14">, DwarfRegNum<[14]>;
- def R15 : GPRReg<15, "r15">, DwarfRegNum<[15]>;
+ def R0 : GPRReg<0, "r0">, DwarfRegNum<[0]>;
+ def R1 : GPRReg<1, "r1">, DwarfRegNum<[1]>;
+ def R2 : GPRReg<2, "r2">, DwarfRegNum<[2]>;
+ def R3 : GPRReg<3, "r3">, DwarfRegNum<[3]>;
+ def R4 : GPRReg<4, "r4">, DwarfRegNum<[4]>;
+ def R5 : GPRReg<5, "r5">, DwarfRegNum<[5]>;
+ def R6 : GPRReg<6, "r6">, DwarfRegNum<[6]>;
+ def R7 : GPRReg<7, "r7">, DwarfRegNum<[7]>;
+ def R8 : GPRReg<8, "r8">, DwarfRegNum<[8]>;
+ def R9 : GPRReg<9, "r9">, DwarfRegNum<[9]>;
+ def R10 : GPRReg<10, "r10">, DwarfRegNum<[10]>;
+ def R11 : GPRReg<11, "r11">, DwarfRegNum<[11]>;
+ def R12 : GPRReg<12, "r12">, DwarfRegNum<[12]>;
+ def R13 : GPRReg<13, "r13">, DwarfRegNum<[13]>;
+ def R14 : GPRReg<14, "r14">, DwarfRegNum<[14]>;
+ def R15 : GPRReg<15, "r15">, DwarfRegNum<[15]>;
// Control Registers
- def SR : CtrlReg<0, "sr">; // Status Register
- def GBR : CtrlReg<0, "gbr">; // Global Base Register
- def VBR : CtrlReg<0, "vbr">; // Vector Base Register
- def SGR : CtrlReg<0, "sgr">; // Saved General Register
- def DBR : CtrlReg<0, "dbr">; // Debug Base Register
- def SSR : CtrlReg<0, "ssr">; // Saved Status Register
- def SPC : CtrlReg<0, "spc">; // Saved Program Counter
+ def SR : CtrlReg<0, "sr">, DwarfRegNum<[22]>; // Status Register
+ def GBR : CtrlReg<0, "gbr">, DwarfRegNum<[18]>; // Global Base Register
+ def VBR : CtrlReg<0, "vbr">, DwarfRegNum<[19]>; // Vector Base Register
+ def SGR : CtrlReg<0, "sgr">, DwarfRegNum<[60]>; // Saved General Register
+ def DBR : CtrlReg<0, "dbr">, DwarfRegNum<[59]>; // Debug Base Register
+ def SSR : CtrlReg<0, "ssr">, DwarfRegNum<[41]>; // Saved Status Register
+ def SPC : CtrlReg<0, "spc">, DwarfRegNum<[42]>; // Saved Program Counter
// System Registers
- def PR : SysReg<0, "pr">; // Procedure Register
- def PC : SysReg<0, "pc">; // Program Counter
- def MACL : SysReg<0, "macl">; // Mult & Accum Low
- def MACH : SysReg<1, "mach">; // Mult & Accum Hi
- def FPSCR : SysReg<0, "fpscr">; // FPU Status/Control Register
- def FPUL : SysReg<0, "fpul">; // FPU Comms Register
+ def PC : SysReg<0, "pc">, DwarfRegNum<[16]>; // Program Counter
+ def PR : SysReg<0, "pr">, DwarfRegNum<[17]>; // Procedure Register
+ def MACH : SysReg<1, "mach">, DwarfRegNum<[20]>; // Mult & Accum Hi
+ def MACL : SysReg<0, "macl">, DwarfRegNum<[21]>; // Mult & Accum Low
+ def FPUL : SysReg<0, "fpul">, DwarfRegNum<[23]>; // FPU Comms Register
+ def FPSCR : SysReg<0, "fpscr">, DwarfRegNum<[24]>; // FPU Status/Control Register
// 32-bit floating point registers
foreach I = 0-15 in
- def FR#I : FRReg<I, "fr"#I>, DwarfRegNum<[!add(I, 16)]>;
+ def FR#I : FRReg<I, "fr"#I>, DwarfRegNum<[!add(I, 25)]>;
foreach I = 0-15 in
- def XF#I : FRReg<!add(I, 16), "xf"#I>, DwarfRegNum<[!add(I, 32)]>;
+ def XF#I : FRReg<!add(I, 16), "xf"#I>, DwarfRegNum<[!add(I, 61)]>;
// 64-bit floating point registers
foreach I = 0-7 in
@@ -188,4 +188,13 @@ def CTRL : RegisterClass<"SH", [ i32 ], 32,
// System registers.
def SYS : RegisterClass<"SH", [ i32 ], 32,
- (add PR, PC, MACL, MACH, FPSCR, FPUL)>, Unallocatable;
\ No newline at end of file
+ (add PR, PC, MACL, MACH, FPSCR, FPUL)>, Unallocatable;
+
+// Program Counter
+def R_PC : RegisterClass<"SH", [ i32 ], 32, (add PC)>, Unallocatable;
+
+// GBR
+def R_GBR : RegisterClass<"SH", [ i32 ], 32, (add GBR)>, Unallocatable;
+
+// R0 Register
+def R_R0 : RegisterClass<"SH", [ i32 ], 32, (add R0)>, Unallocatable;
\ No newline at end of file
>From ac65ce7cf6aff1ff01392568a6e6195c51415c9c Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 6 Aug 2026 12:02:42 +0200
Subject: [PATCH 12/39] remove printf debugging
---
llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 4 ----
1 file changed, 4 deletions(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 2a1c28816c9a4..80a9f8aafa71b 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -102,8 +102,6 @@ void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
unsigned NumBits = Info.TargetSize + Info.TargetOffset;
unsigned NumBytes = (NumBits / 8) + ((NumBits % 8) == 0 ? 0 : 1);
-
- LDBG() << "Writing " << itostr(NumBytes) << " bytes, " << itostr(NumBits) << " bits.";
assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
"Invalid fixup offset!");
@@ -143,8 +141,6 @@ bool SuperHAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
if (!PCITarget.getAddSym())
return false;
- F.dump();
-
// Evaluate as ELF.
auto &SA = static_cast<const MCSymbolELF &>(*PCITarget.getAddSym());
if (SA.isUndefined())
>From 5b33c775fe2ddc29c6161c05bd54ae0a1654edbc Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 7 Aug 2026 01:48:48 +0200
Subject: [PATCH 13/39] Add static fixup support for SH2A + DSP extensions
---
.../SuperH/MCTargetDesc/SuperHFixupKinds.h | 41 +++++++++++++-----
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 42 ++++++++++++++++---
llvm/lib/Target/SuperH/SuperH.td | 4 +-
llvm/lib/Target/SuperH/SuperHInstrBranch.td | 22 +++++-----
4 files changed, 79 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
index 0214153296167..3031c6be31e93 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
@@ -1,4 +1,4 @@
-//===-- SuperHFixupKinds.h - AVR Specific Fixup Entries ---------*- C++ -*-===//
+//===-- SuperHFixupKinds.h - SuperH Specific Fixup Entries ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -21,23 +21,42 @@ namespace SuperH {
/// to be uniquely named.
///
/// \note This table *must* be in the same order of
-/// MCFixupKindInfo Infos[AVR::NumTargetFixupKinds]
-/// in `AVRAsmBackend.cpp`.
+/// MCFixupKindInfo Infos[SuperH::NumTargetFixupKinds]
+/// in `SuperHAsmBackend.cpp`.
enum Fixups {
+ // The following fields follow the instructions in the C ABI Specification
+ // which can be found at https://www.renesas.com/en/document/mat/superh-cc-compiler-package-v904-users-manual?r=1169516
+ //
+ //
+ // Name Value Field Calculation
- // Fixup which uses 12 bits and is PC relative.
- // Used in specific displacement operands.
- fixup_12_pcrel = FirstTargetFixupKind,
+ /// R_SH_GOT32 160 word32 G + A
+ fixup_got32 = FirstTargetFixupKind,
- // Fixup which uses 8 bits and is PC relative.
- fixup_8_pcrel,
+ /// R_SH_GOT_LOW16 169 T_32s10for16 (G + A) & 65535
+ fixup_got_low16,
- // Fixup which uses 4 bits and is PC relative.
- fixup_4_pcrel,
+ /// R_SH_GOT_MEDLOW16 170 T_32u10for16 ((G + A) >> 16) & 65535
+ fixup_got_medlow16,
+
+ /// R_SH_GOT_MEDHI16 171 T_32u10for16 ((G + A) >> 32) & 65535
+ fixup_got_medhi16,
+
+ /// R_SH_GOT_HI16 172 T_32u10for16 ((G + A) >> 48) & 65535
+ fixup_got_hi16,
+
+ /// R_SH_GOT10BY4 189 V_32s10for10 (G + A) / 4
+ fixup_got10by4,
+
+ /// R_SH_GOT10BY8 191 V_32s10for10 (G + A) / 8
+ fixup_got10by8,
+
+ /// R_SH_PLT32 161 word32 L + A - P
+ fixup_plt32,
// Marker
LastTargetFixupKind,
- NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
+ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind,
};
} // namespace SuperH
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index d4d546ef0e443..b3ec85e13f0ba 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -74,17 +74,43 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
#include "SuperHGenMCCodeEmitter.inc"
+// Some SuperH instructions are 32-bits wide.
+// In those instances we want to emit a bigger static
+// fixup.
+static bool isOpcode32(unsigned opcode) {
+
+ // movi20 & movi20s
+ if ((opcode & 0xF00F) <= 0x0001)
+ return true;
+
+ // Other SH2A 32-bit instructions
+ if ((opcode & 0xF00F) == 0x3001)
+ return true;
+
+ // Opcodes bigger than 0xFFFF are always 32-bits.
+ return opcode > 0xFFFF;
+}
+
void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
- // All base instructions are 16-bit in SuperH asm
- uint16_t Bits = (uint16_t)getBinaryCodeForInstr(MI, Fixups, STI);
- support::endian::write(CB, Bits, Ctx.getAsmInfo().isLittleEndian()
- ? llvm::endianness::little
- : llvm::endianness::big);
+ // NOTE: All base instructions are 16-bit in SH ASM
+ // But some instructions may be 32-bit for eg. SH2A or the DSP extensions.
+ // This is ugly, but it'll work.
+ if (isOpcode32(MI.getOpcode())) {
+ uint32_t Bits = (uint32_t)getBinaryCodeForInstr(MI, Fixups, STI);
+ support::endian::write(CB, Bits, Ctx.getAsmInfo().isLittleEndian()
+ ? llvm::endianness::little
+ : llvm::endianness::big);
+ } else {
+ uint16_t Bits = (uint16_t)getBinaryCodeForInstr(MI, Fixups, STI);
+ support::endian::write(CB, Bits, Ctx.getAsmInfo().isLittleEndian()
+ ? llvm::endianness::little
+ : llvm::endianness::big);
+ }
++MCNumEmitted;
}
@@ -101,7 +127,11 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
// Symbol Reference
if (Kind == MCExpr::SymbolRef) {
- Fixups.push_back(MCFixup::create(0, Expr, FK_Data_2, true));
+
+ // NOTE: A few (DSP and SH2A) instructions are 32-bits wide.
+ // We handle those quite crudely.
+ Fixups.push_back(MCFixup::create(0, Expr,
+ isOpcode32(MI.getOpcode()) ? FK_Data_4 : FK_Data_2, true));
return 0;
}
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index 75c2112f854e7..823f4acdc9429 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -131,8 +131,8 @@ def SuperHAsmParser : AsmParser {
def SuperHAsmParserVariant : AsmParserVariant {
let Variant = 0;
let Name = "Hitachi";
- let SeparatorCharacters = " \t,";
- let TokenizingCharacters = "()[]*!#@-+";
+ let SeparatorCharacters = " \t,()@-+";
+ let TokenizingCharacters = "[]*!#";
let CommentDelimiter = ";";
}
diff --git a/llvm/lib/Target/SuperH/SuperHInstrBranch.td b/llvm/lib/Target/SuperH/SuperHInstrBranch.td
index 939dfc2ec6256..3042301268c4e 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrBranch.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrBranch.td
@@ -62,15 +62,15 @@ class BrOpRet<bits<16> op, string opcodestr>
//===-----------------------------------------------------------------------===//
let Namespace = "SH" in {
- def BF_Disp : BrOp_Disp8<0b1000101100000000, "bf">;
- def BFS_Disp : BrOpD_Disp8<0b1000111100000000, "bf/s">;
- def BT_Disp : BrOp_Disp8<0b1000100100000000, "bt">;
- def BTS_Disp : BrOpD_Disp8<0b1000110100000000, "bt/s">;
- def BRA_Disp : BrOp_Disp12<0b1010000000000000, "bra">;
- def BRAF_Rm : BrOp_Rm<0b0000000000100011, "braf">;
- def BSR_Disp : BrOp_Disp12<0b1011000000000000, "bsr">;
- def BSRF_Rm : BrOp_Rm<0b0000000000000011, "bsrf">;
- def JMP_Rmi : BrOp_Rmi<0b0100000000101011, "jmp">;
- def JSR_Rmi : BrOpCall_Rmi<0b0100000000001011, "jsr">;
- def RTS : BrOpRet<0b0000000000001011, "rts">;
+ def BF_Disp : BrOp_Disp8<0b1000101100000000, "bf">;
+ def BFS_Disp : BrOpD_Disp8<0b1000111100000000, "bf/s">;
+ def BT_Disp : BrOp_Disp8<0b1000100100000000, "bt">;
+ def BTS_Disp : BrOpD_Disp8<0b1000110100000000, "bt/s">;
+ def BRA_Disp : BrOp_Disp12<0b1010000000000000, "bra">;
+ def BRAF_Rm : BrOp_Rm<0b0000000000100011, "braf">;
+ def BSR_Disp : BrOp_Disp12<0b1011000000000000, "bsr">;
+ def BSRF_Rm : BrOp_Rm<0b0000000000000011, "bsrf">;
+ def JMP_Rmi : BrOp_Rmi<0b0100000000101011, "jmp">;
+ def JSR_Rmi : BrOpCall_Rmi<0b0100000000001011, "jsr">;
+ def RTS : BrOpRet<0b0000000000001011, "rts">;
}
\ No newline at end of file
>From cb95e4244c1a75d69ffee9c306aef8bc1f71069c Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 7 Aug 2026 04:12:47 +0200
Subject: [PATCH 14/39] Fix NOP emission and 32-bit instruction emission
---
.../SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 25 +++++++++------
.../SuperH/MCTargetDesc/SuperHAsmBackend.h | 2 +-
.../MCTargetDesc/SuperHELFObjectWriter.cpp | 10 ++++--
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 31 ++++++++++---------
4 files changed, 42 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 80a9f8aafa71b..6c35ccade42d8 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -28,6 +28,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
using namespace llvm;
@@ -40,11 +41,17 @@ SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) :
bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
const MCSubtargetInfo *STI) const {
+ const uint16_t SH_NopEnc = 0b0000000000001001;
// If the count is not 4-byte aligned, we must be writing data into the
// text section (otherwise we have unaligned instructions, and thus have
- // far bigger problems), so just write zeros instead.
- OS.write_zeros(Count % 2);
+ // far bigger problems), so just write NOP instructions.
+ uint64_t NumNops = Count / 2;
+ for (uint64_t i = 0; i != NumNops; ++i)
+ support::endian::write(OS, SH_NopEnc, Endian);
+
+ // Write any straggling zeros needed.
+ OS.write_zeros(Count & 1);
return true;
}
std::optional<MCFixupKind> SuperHAsmBackend::getFixupKind(StringRef Name) const {
@@ -89,9 +96,9 @@ void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
uint64_t Value, bool IsResolved) {
// Handle Relocations
- IsResolved = addReloc(F, Fixup, Target, Value, IsResolved);
+ IsResolved = tryAddReloc(F, Fixup, Target, Value, IsResolved);
MCFixupKind Kind = Fixup.getKind();
- if (mc::isRelocation(Kind))
+ if (mc::isRelocation(Kind))
return;
// Handle non-relocations
@@ -115,7 +122,7 @@ void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
}
}
-bool SuperHAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
+bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target, uint64_t &FixedValue,
bool IsResolved) {
@@ -126,10 +133,8 @@ bool SuperHAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
default:
return {};
- case FK_Data_1:
case FK_Data_2:
- case FK_Data_4:
- case FK_Data_8: {
+ case FK_Data_4: {
const auto *EValue = Fixup.getValue();
if (!EValue->evaluateAsRelocatable(PCITarget, Asm))
return true;
@@ -150,8 +155,10 @@ bool SuperHAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
IsResolved = &SA.getSection() == F.getParent() &&
SA.getBinding() == ELF::STB_LOCAL &&
SA.getType() != ELF::STT_GNU_IFUNC;
- if (!IsResolved)
+ if (!IsResolved) {
+ Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
return false;
+ }
// Calculate fixed offset value.
// Note that the PC relative jumps are based on the start of the address.
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
index f0e7e969f2d35..f27ed3891217b 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
@@ -33,7 +33,7 @@ class SuperHAsmBackend : public MCAsmBackend {
MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
uint8_t *Data, uint64_t Value, bool IsResolved) override;
- bool addReloc(const MCFragment &F, const MCFixup &Fixup,
+ bool tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target, uint64_t &FixedValue,
bool IsResolved);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index d74ebf2a297e5..0e337f12d546a 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -11,6 +11,7 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCValue.h"
@@ -40,12 +41,17 @@ namespace llvm {
unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
const MCValue &Target,
bool IsPCRel) const {
- return ELF::R_SH_NONE;
+ auto Kind = Fixup.getKind();
+ uint8_t Specifier = Target.getSpecifier();
+ if (Kind == FK_Data_4 || Kind == FK_Data_2)
+ return ELF::R_SH_NONE;
+
+ return Specifier;
}
bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
unsigned Type) const {
- return false;
+ return true;
}
std::unique_ptr<MCObjectTargetWriter>
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index b3ec85e13f0ba..3f5d826bd1b13 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -13,6 +13,7 @@
#include "SuperHMCTargetDesc.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/bit.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -27,6 +28,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/DebugLog.h"
#include "llvm/Support/EndianStream.h"
#include <cstdint>
@@ -75,38 +77,39 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
#include "SuperHGenMCCodeEmitter.inc"
// Some SuperH instructions are 32-bits wide.
-// In those instances we want to emit a bigger static
-// fixup.
-static bool isOpcode32(unsigned opcode) {
+//
+// Checks the passed opcode for any bit patterns
+// that must be encoded as 32-bits.
+static bool isOpcode32(uint32_t Opcode) {
// movi20 & movi20s
- if ((opcode & 0xF00F) <= 0x0001)
+ if ((Opcode & 0xF00F) <= 0x0001)
return true;
// Other SH2A 32-bit instructions
- if ((opcode & 0xF00F) == 0x3001)
+ if ((Opcode & 0xF00F) == 0x3001)
return true;
// Opcodes bigger than 0xFFFF are always 32-bits.
- return opcode > 0xFFFF;
+ return Opcode > 0xFFFF;
}
void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
+
+ uint32_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
+
// NOTE: All base instructions are 16-bit in SH ASM
// But some instructions may be 32-bit for eg. SH2A or the DSP extensions.
// This is ugly, but it'll work.
- if (isOpcode32(MI.getOpcode())) {
- uint32_t Bits = (uint32_t)getBinaryCodeForInstr(MI, Fixups, STI);
- support::endian::write(CB, Bits, Ctx.getAsmInfo().isLittleEndian()
+ if (isOpcode32(OpCode)) {
+ support::endian::write(CB, (uint32_t)OpCode, Ctx.getAsmInfo().isLittleEndian()
? llvm::endianness::little
: llvm::endianness::big);
} else {
- uint16_t Bits = (uint16_t)getBinaryCodeForInstr(MI, Fixups, STI);
- support::endian::write(CB, Bits, Ctx.getAsmInfo().isLittleEndian()
+ support::endian::write(CB, (uint16_t)OpCode, Ctx.getAsmInfo().isLittleEndian()
? llvm::endianness::little
: llvm::endianness::big);
@@ -130,8 +133,8 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
// NOTE: A few (DSP and SH2A) instructions are 32-bits wide.
// We handle those quite crudely.
- Fixups.push_back(MCFixup::create(0, Expr,
- isOpcode32(MI.getOpcode()) ? FK_Data_4 : FK_Data_2, true));
+ uint32_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
+ Fixups.push_back(MCFixup::create(0, Expr, isOpcode32(OpCode) ? FK_Data_4 : FK_Data_2, true));
return 0;
}
>From 00041ddf66babc4ef53e352c724c27f508dd8d8c Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sat, 8 Aug 2026 15:50:47 +0200
Subject: [PATCH 15/39] Redo SDNode mappings, basic C codegen support infra.
---
clang/lib/Basic/CMakeLists.txt | 1 +
clang/lib/Basic/Targets.cpp | 8 +
clang/lib/Basic/Targets/SuperH.cpp | 67 ++++
clang/lib/Basic/Targets/SuperH.h | 113 ++++++
.../llvm/BinaryFormat/ELFRelocs/SuperH.def | 2 +-
llvm/include/llvm/TargetParser/Triple.h | 5 +
llvm/lib/Target/SuperH/CMakeLists.txt | 7 +-
.../Target/SuperH/MCTargetDesc/CMakeLists.txt | 1 +
.../SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 48 ++-
.../SuperH/MCTargetDesc/SuperHFixupKinds.h | 116 +++++-
.../MCTargetDesc/SuperHMCTargetDesc.cpp | 43 ++-
.../MCTargetDesc/SuperHTargetStreamer.cpp | 37 ++
.../MCTargetDesc/SuperHTargetStreamer.h | 39 ++
llvm/lib/Target/SuperH/SuperH.h | 16 +
llvm/lib/Target/SuperH/SuperH.td | 3 +-
llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp | 99 +++++
llvm/lib/Target/SuperH/SuperHCallingConv.td | 35 +-
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 12 +-
llvm/lib/Target/SuperH/SuperHFrameLowering.h | 2 +
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 148 ++++++++
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 193 ++++++++++
llvm/lib/Target/SuperH/SuperHISelLowering.h | 47 +++
.../Target/SuperH/SuperHInstrArithmetic.td | 77 ----
llvm/lib/Target/SuperH/SuperHInstrBranch.td | 76 ----
llvm/lib/Target/SuperH/SuperHInstrData.td | 172 ---------
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 220 +++++++----
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 22 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 15 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 352 +++++++++++++++---
llvm/lib/Target/SuperH/SuperHMCInstLower.cpp | 78 ++++
llvm/lib/Target/SuperH/SuperHMCInstLower.h | 43 +++
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 76 ++--
llvm/lib/Target/SuperH/SuperHRegisterInfo.h | 11 +-
.../Target/SuperH/SuperHSelectionDAGInfo.cpp | 19 +
.../Target/SuperH/SuperHSelectionDAGInfo.h | 28 ++
llvm/lib/Target/SuperH/SuperHSubtarget.cpp | 29 +-
llvm/lib/Target/SuperH/SuperHSubtarget.h | 45 ++-
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 56 ++-
llvm/lib/Target/SuperH/SuperHTargetMachine.h | 11 +
llvm/lib/TargetParser/TargetDataLayout.cpp | 9 +-
40 files changed, 1819 insertions(+), 562 deletions(-)
create mode 100644 clang/lib/Basic/Targets/SuperH.cpp
create mode 100644 clang/lib/Basic/Targets/SuperH.h
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.h
create mode 100644 llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHISelLowering.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHISelLowering.h
delete mode 100644 llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
delete mode 100644 llvm/lib/Target/SuperH/SuperHInstrBranch.td
delete mode 100644 llvm/lib/Target/SuperH/SuperHInstrData.td
create mode 100644 llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHMCInstLower.h
create mode 100644 llvm/lib/Target/SuperH/SuperHSelectionDAGInfo.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHSelectionDAGInfo.h
diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt
index adfc6ee326b5a..ac7e9a48f868b 100644
--- a/clang/lib/Basic/CMakeLists.txt
+++ b/clang/lib/Basic/CMakeLists.txt
@@ -115,6 +115,7 @@ add_clang_library(clangBasic
Targets/RISCV.cpp
Targets/SPIR.cpp
Targets/Sparc.cpp
+ Targets/SuperH.cpp
Targets/SystemZ.cpp
Targets/TCE.cpp
Targets/VE.cpp
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 0a1938b0bebd3..d6e73b6678f3f 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -33,6 +33,7 @@
#include "Targets/RISCV.h"
#include "Targets/SPIR.h"
#include "Targets/Sparc.h"
+#include "Targets/SuperH.h"
#include "Targets/SystemZ.h"
#include "Targets/TCE.h"
#include "Targets/VE.h"
@@ -551,6 +552,13 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
default:
return std::make_unique<SparcV9TargetInfo>(Triple, Opts);
}
+
+ case llvm::Triple::sh:
+ case llvm::Triple::sh_le:
+ switch (os) {
+ default:
+ return std::make_unique<SuperHTargetInfo>(Triple, Opts);
+ }
case llvm::Triple::systemz:
switch (os) {
diff --git a/clang/lib/Basic/Targets/SuperH.cpp b/clang/lib/Basic/Targets/SuperH.cpp
new file mode 100644
index 0000000000000..2aa91c1a2fea1
--- /dev/null
+++ b/clang/lib/Basic/Targets/SuperH.cpp
@@ -0,0 +1,67 @@
+//===--- SuperH.cpp - Declare SuperH target feature support -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares SuperH TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperH.h"
+#include "clang/Basic/MacroBuilder.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+struct LLVM_LIBRARY_VISIBILITY SHCPUInfo {
+ llvm::StringLiteral Name;
+};
+
+static constexpr SHCPUInfo CPUInfo[] = {
+ {{"sh1"}},
+ {{"sh2"}},
+ {{"sh2a"}},
+ {{"sh3"}},
+ {{"sh4"}},
+ {{"sh4a"}},
+};
+
+bool SuperHTargetInfo::isValidCPUName(StringRef Name) const {
+ return llvm::any_of(
+ CPUInfo, [&](const SHCPUInfo &Info) { return Info.Name == Name; });
+}
+
+void SuperHTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+ for (const SHCPUInfo &Info : CPUInfo)
+ Values.push_back(Info.Name);
+}
+
+bool SuperHTargetInfo::setCPU(const std::string &Name) {
+ // Set the ABI field based on the device or family name.
+ const auto *It = llvm::find_if(
+ CPUInfo, [&](const SHCPUInfo &Info) { return Info.Name == Name; });
+ if (It != std::end(CPUInfo)) {
+ CPU = Name;
+ ABI = "sh";
+ return true;
+ }
+
+ // Parameter Name is neither valid family name nor valid device name.
+ return false;
+}
+
+std::optional<std::string>
+SuperHTargetInfo::handleAsmEscapedChar(char EscChar) const {
+ return std::nullopt;
+}
+
+void SuperHTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("SH");
+ Builder.defineMacro("__SH");
+ Builder.defineMacro("__SH__");
+}
\ No newline at end of file
diff --git a/clang/lib/Basic/Targets/SuperH.h b/clang/lib/Basic/Targets/SuperH.h
new file mode 100644
index 0000000000000..2f96a6895c7d3
--- /dev/null
+++ b/clang/lib/Basic/Targets/SuperH.h
@@ -0,0 +1,113 @@
+//===--- SuperH.h - Declare SuperH target feature support -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares SuperH TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SUPERH_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_SUPERH_H
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/TargetParser/Triple.h"
+
+namespace clang {
+namespace targets {
+
+// SuperH Target
+class LLVM_LIBRARY_VISIBILITY SuperHTargetInfo : public TargetInfo {
+public:
+ SuperHTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ : TargetInfo(Triple) {
+ TLSSupported = false;
+ PointerWidth = 32;
+ PointerAlign = 32;
+ ShortWidth = 16;
+ ShortAlign = 32;
+ IntWidth = 32;
+ IntAlign = 32;
+ LongWidth = 32;
+ LongAlign = 32;
+ LongLongWidth = 64;
+ LongLongAlign = 64;
+ SuitableAlign = 32;
+ DefaultAlignForAttributeAligned = 32;
+ HalfWidth = 16;
+ HalfAlign = 32;
+ FloatWidth = 32;
+ FloatAlign = 32;
+ DoubleWidth = 32;
+ DoubleAlign = 32;
+ DoubleFormat = &llvm::APFloat::IEEEsingle();
+ LongDoubleWidth = 64;
+ LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+ Char16Type = UnsignedShort;
+ WIntType = SignedInt;
+ Int16Type = SignedShort;
+ Char32Type = UnsignedLong;
+ SigAtomicType = SignedChar;
+ resetDataLayout();
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+
+ llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
+ return {};
+ }
+
+ bool allowsLargerPreferedTypeAlignment() const override { return false; }
+
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+
+ std::string_view getClobbers() const override { return ""; }
+
+ ArrayRef<const char *> getGCCRegNames() const override {
+ static const char *const GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ };
+ return llvm::ArrayRef(GCCRegNames);
+ }
+
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return {};
+ }
+
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ return false;
+ }
+
+ bool isValidCPUName(StringRef Name) const override;
+ void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
+ bool setCPU(const std::string &Name) override;
+ std::optional<std::string> handleAsmEscapedChar(char EscChar) const override;
+ StringRef getABI() const override { return ABI; }
+
+ std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
+ return std::make_pair(32, 32);
+ }
+
+protected:
+ std::string CPU;
+ StringRef ABI;
+};
+
+}
+}
+
+#endif
\ No newline at end of file
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
index cc06af4cbb968..943ae7dd39440 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
@@ -18,7 +18,7 @@ ELF_RELOC(R_SH_GOT10BY4, 189)
ELF_RELOC(R_SH_GOT10BY8, 191)
ELF_RELOC(R_SH_PLT32, 161)
ELF_RELOC(R_SH_PLT_LOW16, 177)
-ELF_RELOC(R_SH_PLT_MEWLOW16, 178)
+ELF_RELOC(R_SH_PLT_MEDLOW16, 178)
ELF_RELOC(R_SH_PLT_MEDHI16, 179)
ELF_RELOC(R_SH_PLT_HI16, 180)
ELF_RELOC(R_SH_GOTPLT32, 168)
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 375e96c6486f0..709137eacb9e0 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -1106,6 +1106,11 @@ class Triple {
/// Tests whether the target is SPARC.
bool isSPARC() const { return isSPARC32() || isSPARC64(); }
+ /// Tests whether the target is SuperH.
+ bool isSuperH() const {
+ return getArch() == Triple::sh || getArch() == Triple::sh_le;
+ }
+
/// Tests whether the target is SystemZ.
bool isSystemZ() const { return getArch() == Triple::systemz; }
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index f0d4a594242a9..535e9d53b2853 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -4,8 +4,8 @@ set(LLVM_TARGET_DEFINITIONS SuperH.td)
tablegen(LLVM SuperHGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM SuperHGenAsmWriter.inc -gen-asm-writer)
-tablegen(LLVM SuperHGenCallingConv.inc -gen-callingconv)
tablegen(LLVM SuperHGenDAGISel.inc -gen-dag-isel)
+tablegen(LLVM SuperHGenCallingConv.inc -gen-callingconv)
tablegen(LLVM SuperHGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM SuperHGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM SuperHGenInstrInfo.inc -gen-instr-info)
@@ -20,6 +20,11 @@ add_llvm_target(SuperHCodeGen
SuperHTargetMachine.cpp
SuperHFrameLowering.cpp
SuperHRegisterInfo.cpp
+ SuperHMCInstLower.cpp
+ SuperHSelectionDAGInfo.cpp
+ SuperHISelDAGToDAG.cpp
+ SuperHISelLowering.cpp
+ SuperHAsmPrinter.cpp
SuperHInstrInfo.cpp
SuperHSubtarget.cpp
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
index c0bbc3c43df5b..20ea892292481 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
@@ -4,6 +4,7 @@ add_llvm_component_library(LLVMSuperHDesc
SuperHMCAsmInfo.cpp
SuperHInstPrinter.cpp
SuperHELFObjectWriter.cpp
+ SuperHTargetStreamer.cpp
SuperHAsmBackend.cpp
LINK_COMPONENTS
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 6c35ccade42d8..26bfcbbca5b03 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -69,15 +69,53 @@ std::optional<MCFixupKind> SuperHAsmBackend::getFixupKind(StringRef Name) const
}
MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
+ // clang-format off
const static MCFixupKindInfo Infos[SuperH::NumTargetFixupKinds] = {
// This table *must* be in same the order of fixup_* kinds in
- // AVRFixupKinds.h.
+ // SuperHFixupKinds.h.
//
- // name offset bits flags
- {"fixup_12_pcrel", 12, 16, 0},
- {"fixup_8_pcrel", 8, 16, 0},
- {"fixup_4_pcrel", 4, 16, 0},
+ // Name offset bits flags
+ {"fixup_got32", 0, 32, 0},
+ {"fixup_got_low16", 10, 16, 0},
+ {"fixup_got_medlow16", 10, 16, 0},
+ {"fixup_got_medhi16", 10, 16, 0},
+ {"fixup_got_hi16", 10, 16, 0},
+ {"fixup_got10by4", 10, 10, 0},
+ {"fixup_got10by8", 10, 10, 0},
+ {"fixup_plt32", 0, 32, 0},
+ {"fixup_plt_low16", 10, 16, 0},
+ {"fixup_plt_medlow16", 10, 16, 0},
+ {"fixup_plt_medhi16", 10, 16, 0},
+ {"fixup_plt_hi16", 10, 16, 0},
+ {"fixup_gotplt32", 0, 32, 0},
+ {"fixup_gotplt_low16", 10, 16, 0},
+ {"fixup_gotplt_medlow16", 10, 16, 0},
+ {"fixup_gotplt_medhi16", 10, 16, 0},
+ {"fixup_gotplt_hi16", 10, 16, 0},
+ {"fixup_gotoff", 0, 32, 0},
+ {"fixup_gotoff_low16", 10, 16, 0},
+ {"fixup_gotoff_medlow16", 10, 16, 0},
+ {"fixup_gotoff_medhi16", 10, 16, 0},
+ {"fixup_gotoff_hi16", 10, 16, 0},
+ {"fixup_gotpc", 0, 32, 0},
+ {"fixup_gotpc_low16" , 10, 16, 0},
+ {"fixup_gotpc_medlow16" , 10, 16, 0},
+ {"fixup_gotpc_medhi16" , 10, 16, 0},
+ {"fixup_gotpc_hi16" , 10, 16, 0},
+ {"fixup_copy", 0, 0, 0},
+ {"fixup_copy64", 0, 0, 0},
+ {"fixup_glob_dat", 0, 32, 0},
+ {"fixup_glob_dat64", 0, 64, 0},
+ {"fixup_jump_slot", 0, 32, 0},
+ {"fixup_jump_slot64", 0, 64, 0},
+ {"fixup_relative", 0, 32, 0},
+ {"fixup_relative64", 0, 64, 0},
+ {"fixup_dir32", 0, 32, 0},
+ {"fixup_rel32", 0, 32, 0},
+ {"fixup_64", 0, 64, 0},
+ {"fixup_64_pcrel", 0, 64, 0},
};
+ // clang-format on
if (mc::isRelocation(Kind))
return {};
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
index 3031c6be31e93..ee8865c44bb26 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
@@ -14,6 +14,8 @@
namespace llvm {
namespace SuperH {
+// clang-format off
+
/// The set of supported fixups.
///
/// Although most of the current fixup types reflect a unique relocation
@@ -27,33 +29,129 @@ enum Fixups {
// The following fields follow the instructions in the C ABI Specification
// which can be found at https://www.renesas.com/en/document/mat/superh-cc-compiler-package-v904-users-manual?r=1169516
//
+ // NOTE: Some relocation names are misspelled in the official manual,
+ // The misspellings are corrected as follows:
+ // - R_SH_PLT_MEWLOW16 -> R_SH_PLT_MEDLOW16
//
- // Name Value Field Calculation
+ // Name Value Field Calculation
- /// R_SH_GOT32 160 word32 G + A
+ // R_SH_GOT32 160 word32 G + A
fixup_got32 = FirstTargetFixupKind,
- /// R_SH_GOT_LOW16 169 T_32s10for16 (G + A) & 65535
+ // R_SH_GOT_LOW16 169 T_32s10for16 (G + A) & 65535
fixup_got_low16,
- /// R_SH_GOT_MEDLOW16 170 T_32u10for16 ((G + A) >> 16) & 65535
+ // R_SH_GOT_MEDLOW16 170 T_32u10for16 ((G + A) >> 16) & 65535
fixup_got_medlow16,
- /// R_SH_GOT_MEDHI16 171 T_32u10for16 ((G + A) >> 32) & 65535
+ // R_SH_GOT_MEDHI16 171 T_32u10for16 ((G + A) >> 32) & 65535
fixup_got_medhi16,
- /// R_SH_GOT_HI16 172 T_32u10for16 ((G + A) >> 48) & 65535
+ // R_SH_GOT_HI16 172 T_32u10for16 ((G + A) >> 48) & 65535
fixup_got_hi16,
- /// R_SH_GOT10BY4 189 V_32s10for10 (G + A) / 4
+ // R_SH_GOT10BY4 189 V_32s10for10 (G + A) / 4
fixup_got10by4,
- /// R_SH_GOT10BY8 191 V_32s10for10 (G + A) / 8
+ // R_SH_GOT10BY8 191 V_32s10for10 (G + A) / 8
fixup_got10by8,
- /// R_SH_PLT32 161 word32 L + A - P
+ // R_SH_PLT32 161 word32 L + A - P
fixup_plt32,
+ // R_SH_PLT_LOW16 177 T_32s10for16 (L + A - P) & 65535
+ fixup_plt_low16,
+
+ // R_SH_PLT_MEDLOW16 178 T_32u10for16 ((L + A - P) >> 16) & 65535
+ fixup_plt_medlow16,
+
+ // R_SH_PLT_MEDHI16 179 T_32u10for16 ((L + A - P) >> 32) & 65535
+ fixup_plt_medhi16,
+
+ // R_SH_PLT_HI16 180 T_32u10for16 ((L + A - P) >> 48) & 65535
+ fixup_plt_hi16,
+
+ // R_SH_GOTPLT32 168 word32 G + A
+ fixup_gotplt32,
+
+ // R_SH_GOTPLT_LOW16 169 T_32s10for16 (G + A) & 65535
+ fixup_gotplt_low16,
+
+ // R_SH_GOTPLT_MEDLOW16 170 T_32u10for16 ((G + A) >> 16) & 65535
+ fixup_gotplt_medlow16,
+
+ // R_SH_GOTPLT_MEDHI16 171 T_32u10for16 ((G + A) >> 32) & 65535
+ fixup_gotplt_medhi16,
+
+ // R_SH_GOTPLT_HI16 172 T_32u10for16 ((G + A) >> 48) & 65535
+ fixup_gotplt_hi16,
+
+ // R_SH_GOTOFF 166 word32 S + A - GOT
+ fixup_gotoff,
+
+ // R_SH_GOTOFF_LOW16 181 T_32s10for16 (S + A - GOT) & 65535
+ fixup_gotoff_low16,
+
+ // R_SH_GOTOFF_MEDLOW16 182 T_32u10for16 ((S + A - GOT) >> 16) & 65535
+ fixup_gotoff_medlow16,
+
+ // R_SH_GOTOFF_MEDHI16 183 T_32u10for16 ((S + A - GOT) >> 32) & 65535
+ fixup_gotoff_medhi16,
+
+ // R_SH_GOTOFF_HI16 184 T_32u10for16 ((S + A - GOT) >> 48) & 65535
+ fixup_gotoff_hi16,
+
+ // R_SH_GOTPC 167 word32 GOT + A - P
+ fixup_gotpc,
+
+ // R_SH_GOTPC_LOW16 185 T_32s10for16 (GOT + A - P) & 65535
+ fixup_gotpc_low16,
+
+ // R_SH_GOTPC_MEDLOW16 186 T_32u10for16 ((GOT + A - P) >> 16) & 65535
+ fixup_gotpc_medlow16,
+
+ // R_SH_GOTPC_MEDHI16 187 T_32u10for16 ((GOT + A - P) >> 32) & 65535
+ fixup_gotpc_medhi16,
+
+ // R_SH_GOTPC_HI16 188 T_32u10for16 ((GOT + A - P) >> 48) & 65535
+ fixup_gotpc_hi16,
+
+ // R_SH_COPY 162 none none
+ fixup_copy,
+
+ // R_SH_COPY64 193 none none
+ fixup_copy64,
+
+ // R_SH_GLOB_DAT 163 word32 S
+ fixup_glob_dat,
+
+ // R_SH_GLOB_DAT64 194 word64 S
+ fixup_glob_dat64,
+
+ // R_SH_JMP_SLOT 164 word32 S
+ fixup_jump_slot,
+
+ // R_SH_JMP_SLOT64 195 word64 S
+ fixup_jump_slot64,
+
+ // R_SH_RELATIVE 165 word32 B + A
+ fixup_relative,
+
+ // R_SH_RELATIVE64 196 word64 B + A
+ fixup_relative64,
+
+ // R_SH_DIR32 1 word32 S + A
+ fixup_dir32,
+
+ // R_SH_REL32 2 word32 S + A - P
+ fixup_rel32,
+
+ // R_SH_64 254 word64 S + A
+ fixup_64,
+
+ // R_SH_64_PCREL 255 word64 S + A - P
+ fixup_64_pcrel,
+
// Marker
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind,
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
index 15f6cc8195b54..8aaa8a3040d43 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
@@ -15,6 +15,7 @@
#include "SuperHMCTargetDesc.h"
#include "SuperHInstPrinter.h"
#include "SuperHMCAsmInfo.h"
+#include "SuperHTargetStreamer.h"
#include "TargetInfo/SuperHTargetInfo.h"
#include "llvm/MC/MCELFStreamer.h"
@@ -35,12 +36,12 @@ using namespace llvm;
#define ENABLE_INSTR_PREDICATE_VERIFIER
#include "SuperHGenInstrInfo.inc"
-#define GET_REGINFO_MC_DESC
-#include "SuperHGenRegisterInfo.inc"
-
#define GET_SUBTARGETINFO_MC_DESC
#include "SuperHGenSubtargetInfo.inc"
+#define GET_REGINFO_MC_DESC
+#include "SuperHGenRegisterInfo.inc"
+
static MCInstrInfo *createSuperHMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitSuperHMCInstrInfo(X);
@@ -73,6 +74,21 @@ static MCAsmInfo *createSuperHMCAsmInfo(const MCRegisterInfo &MRI,
return MAI;
}
+static MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) {
+ return new SuperHTargetStreamer(S);
+}
+
+static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS,
+ MCInstPrinter *InstPrint) {
+ return new SuperHTargetAsmStreamer(S, OS);
+}
+
+static MCTargetStreamer *
+createTargetObjectStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
+ return new SuperHTargetELFStreamer(S, STI);
+}
+
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeSuperHTargetMC() {
for (Target *T : {&getTheSuperHTarget(), &getTheSuperHLETarget()}) {
@@ -85,17 +101,26 @@ LLVMInitializeSuperHTargetMC() {
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(*T, createSuperHMCSubtargetInfo);
-
- // Register the MC asm info.
- TargetRegistry::RegisterMCAsmInfo(*T, createSuperHMCAsmInfo);
-
- // Register the MCInstPrinter.
- TargetRegistry::RegisterMCInstPrinter(*T, createSuperHMCInstPrinter);
// Register the MCCodeEmitter.
TargetRegistry::RegisterMCCodeEmitter(*T, createSuperHMCCodeEmitter);
// Register the AsmBackend
TargetRegistry::RegisterMCAsmBackend(*T, createSuperHAsmBackend);
+
+ // Register the MC asm info.
+ TargetRegistry::RegisterMCAsmInfo(*T, createSuperHMCAsmInfo);
+
+ // Register the object target streamer.
+ TargetRegistry::RegisterObjectTargetStreamer(*T, createTargetObjectStreamer);
+
+ // Register the asm streamer.
+ TargetRegistry::RegisterAsmTargetStreamer(*T, createTargetAsmStreamer);
+
+ // Register the null streamer.
+ TargetRegistry::RegisterNullTargetStreamer(*T, createNullTargetStreamer);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(*T, createSuperHMCInstPrinter);
}
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
new file mode 100644
index 0000000000000..cd8db84311001
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
@@ -0,0 +1,37 @@
+//===-- SuperHTargetStreamer.cpp - SuperH Target Streamer ------*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHTargetStreamer.h"
+#include "SuperHInstPrinter.h"
+#include "SuperHMCTargetDesc.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCRegister.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/FormattedStream.h"
+
+using namespace llvm;
+
+SuperHTargetStreamer::SuperHTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
+
+SuperHTargetAsmStreamer::SuperHTargetAsmStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS)
+ : SuperHTargetStreamer(S), OS(OS) {}
+
+SuperHTargetELFStreamer::SuperHTargetELFStreamer(MCStreamer &S,
+ const MCSubtargetInfo &STI)
+ : SuperHTargetStreamer(S) {
+ ELFObjectWriter &W = getStreamer().getWriter();
+ unsigned EFlags = W.getELFHeaderEFlags();
+
+ W.setELFHeaderEFlags(EFlags);
+}
+
+MCELFStreamer &SuperHTargetELFStreamer::getStreamer() {
+ return static_cast<MCELFStreamer &>(Streamer);
+}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.h
new file mode 100644
index 0000000000000..18b0819c744b7
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.h
@@ -0,0 +1,39 @@
+//===-- SuperHTargetStreamer.h - SuperH Target Streamer --------*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHTARGETSTREAMER_H
+#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHTARGETSTREAMER_H
+
+#include "llvm/MC/MCELFStreamer.h"
+#include "llvm/MC/MCStreamer.h"
+
+namespace llvm {
+class formatted_raw_ostream;
+
+class SuperHTargetStreamer : public MCTargetStreamer {
+public:
+ SuperHTargetStreamer(MCStreamer &S);
+};
+
+// This part is for ascii assembly output
+class SuperHTargetAsmStreamer : public SuperHTargetStreamer {
+ formatted_raw_ostream &OS;
+
+public:
+ SuperHTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
+};
+
+// This part is for ELF object output
+class SuperHTargetELFStreamer : public SuperHTargetStreamer {
+public:
+ SuperHTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
+ MCELFStreamer &getStreamer();
+};
+} // end namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index 931aeffd2c142..75fdde6c8b6a0 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -16,4 +16,20 @@
#include "MCTargetDesc/SuperHMCTargetDesc.h"
+using namespace llvm;
+namespace llvm {
+class AsmPrinter;
+class FunctionPass;
+class MCInst;
+class MachineInstr;
+class PassRegistry;
+class SuperHTargetMachine;
+
+FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel);
+
+void initializeSuperHDAGToDAGISelLegacyPass(PassRegistry &);
+void initializeSuperHAsmPrinterPass(PassRegistry &);
+} // namespace llvm
+
+
#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index 823f4acdc9429..fad2c4fb6f106 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -109,6 +109,7 @@ def SuperHInstrInfo : InstrInfo;
// Calling Conventions
//===----------------------------------------------------------------------===//
+include "SuperHCallingConv.td"
//===---------------------------------------------------------------------===//
// Assembly Printers
@@ -130,7 +131,7 @@ def SuperHAsmParser : AsmParser {
def SuperHAsmParserVariant : AsmParserVariant {
let Variant = 0;
- let Name = "Hitachi";
+ let Name = "GCC";
let SeparatorCharacters = " \t,()@-+";
let TokenizingCharacters = "[]*!#";
let CommentDelimiter = ";";
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
new file mode 100644
index 0000000000000..c62e23430d2b5
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -0,0 +1,99 @@
+//===-- SuperHAsmPrinter.cpp - SH LLVM Assembly Printer ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-----------------------------------------------------------------------===//
+//
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to GAS-format SuperH assembly language.
+//
+//===-----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SuperHInstPrinter.h"
+#include "MCTargetDesc/SuperHMCAsmInfo.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "MCTargetDesc/SuperHTargetStreamer.h"
+#include "SuperH.h"
+#include "SuperHMCInstLower.h"
+#include "TargetInfo/SuperHTargetInfo.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+namespace {
+
+class SuperHAsmPrinter : public AsmPrinter {
+ SuperHTargetStreamer &getTargetStreamer() {
+ return static_cast<SuperHTargetStreamer &>(
+ *OutStreamer->getTargetStreamer());
+ }
+
+public:
+ explicit SuperHAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> Streamer)
+ : AsmPrinter(TM, std::move(Streamer), ID) {}
+
+ StringRef getPassName() const override { return "SuperH Assembly Printer"; }
+
+ void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
+ void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
+
+ void emitFunctionBodyStart() override;
+ void emitInstruction(const MachineInstr *MI) override;
+
+ static const char *getRegisterName(MCRegister Reg) {
+ return SuperHInstPrinter::getRegisterName(Reg);
+ }
+
+ bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ const char *ExtraCode, raw_ostream &O) override;
+ bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+ const char *ExtraCode, raw_ostream &O) override;
+
+ static char ID;
+};
+
+} // namespace
+
+
+void SuperHAsmPrinter::emitFunctionBodyStart() {
+ AsmPrinter::emitFunctionBodyStart();
+}
+
+void SuperHAsmPrinter::emitInstruction(const MachineInstr *MI) {
+ SuperHMCInstLower MCInstLowering(OutContext, *this);
+
+ MCInst I;
+ MCInstLowering.lowerInstruction(*MI, I);
+ EmitToStreamer(*OutStreamer, I);
+}
+
+bool SuperHAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ const char *ExtraCode, raw_ostream &O) {
+ if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
+ return false;
+
+
+ return false;
+}
+
+bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+ const char *ExtraCode, raw_ostream &O) {
+ return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, O);
+}
+
+char SuperHAsmPrinter::ID = 0;
+INITIALIZE_PASS(SuperHAsmPrinter, "sh-asm-printer", "SuperH Assembly Printer", false, false)
+
+// Force static initialization.
+extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
+LLVMInitializeSuperHAsmPrinter() {
+ RegisterAsmPrinter<SuperHAsmPrinter> X(getTheSuperHTarget());
+ RegisterAsmPrinter<SuperHAsmPrinter> Y(getTheSuperHLETarget());
+}
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index ba6ac8c025335..6ce14d5d0c8a9 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -11,19 +11,9 @@
//===-------------------------------------------------------------------------===//
// SuperH CDECL Calling Convention
//===-------------------------------------------------------------------------===//
-let Entry = 1 in
-def CC_SH_CDECL : CallingConv<[
- // Handles byval parameters.
- CCIfByVal<CCPassByVal<4, 4>>,
- CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
-
- CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
- CCIfType<[i32], CCAssignToStack<4, 4>>,
- CCIfType<[f32], CCAssignToStack<4, 4>>,
-]>;
-
-def CC_SH_RENESAS : CallingConv<[
+def CC_SH : CallingConv<[
+ CCIfSRet<CCCustom<"RetCC_SuperH_SRet">>,
// Handles byval parameters.
CCIfByVal<CCPassByVal<4, 4>>,
@@ -34,27 +24,14 @@ def CC_SH_RENESAS : CallingConv<[
CCIfType<[f32], CCAssignToStack<4, 4>>,
]>;
-def CC_SH_WinCE : CallingConv<[
-
- // Handles byval parameters.
- CCIfByVal<CCPassByVal<4, 4>>,
- CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
-
- CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
- CCIfType<[i32], CCAssignToStack<4, 4>>,
- CCIfType<[f32], CCAssignToStack<4, 4>>,
+def RetCC_SH : CallingConv<[
+ CCIfType<[i32], CCAssignToReg<[R0]>>,
+ CCIfType<[i64], CCAssignToReg<[R0, R1]>>
]>;
//===----------------------------------------------------------------------===//
// Callee-saved register lists.
//===----------------------------------------------------------------------===//
-def CSR_SH_CDECL : CalleeSavedRegs<(add R8, R9, R10, R11, R12,
- R13, R14, R15)>;
-
-def CSR_SH_RENESAS : CalleeSavedRegs<(add R4, R5, R6, R7, R8,
- R9, R10, R11, R12, R13,
- R14, R15)>;
-
-def CSR_SH_WINCE : CalleeSavedRegs<(add R8, R9, R10, R11, R12,
+def CSR_SH : CalleeSavedRegs<(add R8, R9, R10, R11, R12,
R13, R14, R15)>;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index ccd3340a45856..a96ea010c27ab 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -22,14 +22,24 @@ using namespace llvm;
void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+ // If function is naked, don't emit prologue.
+ if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
+ return;
+ }
+
}
void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+ // If function is naked, don't emit epilogue.
+ if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
+ return;
+ }
}
bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
- return true;
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ return hasFP(MF) && !MFI.hasVarSizedObjects();
}
MachineBasicBlock::iterator
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index 97eece4398642..c303baa4311d1 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -42,6 +42,8 @@ class SuperHFrameLowering : public TargetFrameLowering {
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const override;
+protected:
+ bool hasFPImpl(const MachineFunction &MF) const override { return false; }
};
} // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
new file mode 100644
index 0000000000000..645e2884e269f
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -0,0 +1,148 @@
+//===- SuperHIDAGToDAG.cpp - A dag to dag inst selector for SH -*- 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 SuperHIDAGToDAG class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperH.h"
+#include "SuperHSubtarget.h"
+#include "SuperHTargetMachine.h"
+#include "SuperHSelectionDAGInfo.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+
+#define DEBUG_TYPE "sh-isel"
+#define PASS_NAME "SH DAG->DAG Instruction Selection"
+
+using namespace llvm;
+
+namespace {
+
+/// Lowers LLVM IR (in DAG form) to SuperH MC instructions (in DAG form).
+class SuperHDAGToDAGISel : public SelectionDAGISel {
+public:
+ SuperHDAGToDAGISel() = delete;
+
+ SuperHDAGToDAGISel(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel)
+ : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {}
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+ bool SelectInlineAsmMemoryOperand(const SDValue &Op,
+ InlineAsm::ConstraintCode ConstraintCode,
+ std::vector<SDValue> &OutOps) override;
+ bool trySelectRET(SDNode *N);
+ bool trySelectFrameIndex(SDNode *N);
+
+// Include the pieces autogenerated from the target description.
+#include "SuperHGenDAGISel.inc"
+
+private:
+ void Select(SDNode *N) override;
+ bool trySelect(SDNode *N);
+
+ const SuperHSubtarget *Subtarget;
+};
+
+class SuperHDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
+public:
+ static char ID;
+ explicit SuperHDAGToDAGISelLegacy(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel)
+ : SelectionDAGISelLegacy(ID, std::make_unique<SuperHDAGToDAGISel>(TM, OptLevel)) {}
+};
+} // end anonymous namespace
+
+char SuperHDAGToDAGISelLegacy::ID = 0;
+
+INITIALIZE_PASS(SuperHDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
+
+bool SuperHDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
+ Subtarget = &MF.getSubtarget<SuperHSubtarget>();
+ return SelectionDAGISel::runOnMachineFunction(MF);
+}
+
+bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
+ InlineAsm::ConstraintCode ConstraintCode,
+ std::vector<SDValue> &OutOps) {
+ return false;
+}
+
+// Due to delay slots there needs to be a bit more smarts
+// in here.
+bool SuperHDAGToDAGISel::trySelectRET(SDNode *N) {
+ SDValue Chain = N->getOperand(0);
+ unsigned LastOpNum = N->getNumOperands() - 1;
+
+ // Skip the incoming flag if present
+ if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
+ --LastOpNum;
+ }
+
+ SDLoc DL(N);
+ SmallVector<SDValue, 8> Ops;
+
+ // RTS implicitly depends on the R0 register for
+ // return values.
+ Ops.push_back(CurDAG->getRegister(SH::R0, MVT::i32));
+ Ops.push_back(Chain);
+ Ops.push_back(Chain.getValue(1));
+
+ SDNode *ResNode = CurDAG->getMachineNode(SH::RTS, DL, MVT::Other, Ops);
+ ResNode = CurDAG->getMachineNode(SH::NOP, DL, MVT::Other, SDValue(ResNode, 0));
+
+ ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
+ CurDAG->RemoveDeadNode(N);
+ return true;
+}
+
+bool SuperHDAGToDAGISel::trySelectFrameIndex(SDNode *N) {
+ auto DL = CurDAG->getDataLayout();
+
+ // Get the effective address of the stack slot.
+ int FI = cast<FrameIndexSDNode>(N)->getIndex();
+ SDValue TFI = CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(DL));
+ CurDAG->SelectNodeTo(N, SH::SHFrmIdx, getTargetLowering()->getPointerTy(DL),
+ TFI, CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32));
+ return true;
+}
+
+bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
+ unsigned Opcode = N->getOpcode();
+ switch(Opcode) {
+ case ISD::FrameIndex:
+ return trySelectFrameIndex(N);
+ case SHISD::RET:
+ return trySelectRET(N);
+ default:
+ return false;
+ }
+}
+
+void SuperHDAGToDAGISel::Select(SDNode *N) {
+
+ // Node was already selected?
+ if (N->isMachineOpcode()) {
+ N->setNodeId(-1);
+ return;
+ }
+
+ // Otherwise try selecting with custom selector
+ if (trySelect(N))
+ return;
+
+ // TableGen fallback
+ SelectCode(N);
+}
+
+FunctionPass *llvm::createSuperHISelDag(SuperHTargetMachine &TM,
+ CodeGenOptLevel OptLevel) {
+ return new SuperHDAGToDAGISelLegacy(TM, OptLevel);
+}
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
new file mode 100644
index 0000000000000..46346fe72f9a3
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -0,0 +1,193 @@
+//===-- SuperHISelLowering.cpp - SH DAG Lowering Interface ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that SuperH uses to lower LLVM code into a
+// selection DAG.
+//
+//===-----------------------------------------------------------------------===//
+
+#include "SuperHISelLowering.h"
+#include "SuperHSelectionDAGInfo.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "SuperHRegisterInfo.h"
+#include "SuperHTargetMachine.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/DebugLog.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-lower"
+
+static bool RetCC_SuperH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
+ CCValAssign::LocInfo &LocInfo,
+ ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+ assert (ArgFlags.isSRet());
+
+ // Assign SRet argument.
+ State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
+ 0,
+ LocVT, LocInfo));
+ return true;
+}
+
+
+#include "SuperHGenCallingConv.inc"
+
+SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
+ const SuperHSubtarget &STI)
+ : TargetLowering(TM, STI), Subtarget(&STI) {
+
+ // GPR Registers are always 32 bit on SuperH.
+ addRegisterClass(MVT::i32, &SH::GPRRegClass);
+ computeRegisterProperties(Subtarget->getRegisterInfo());
+
+
+ setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent);
+ setStackPointerRegisterToSaveRestore(SH::GBR);
+ setJumpIsExpensive(true);
+ setMinFunctionAlignment(Align(4));
+}
+
+SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
+ CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ const SDLoc &dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ MachineRegisterInfo &RegInfo = MF.getRegInfo();
+ DataLayout DL = DAG.getDataLayout();
+
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
+
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext());
+ CCInfo.AnalyzeFormalArguments(Ins, CC_SH);
+
+ unsigned InIdx = 0;
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
+ CCValAssign &VA = ArgLocs[i];
+ SDValue Arg;
+
+ if (VA.isRegLoc()) {
+ Register VReg = RegInfo.createVirtualRegister(&SH::GPRRegClass);
+ MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
+ Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
+ if (VA.getLocInfo() != CCValAssign::Indirect) {
+ if (VA.getLocVT() == MVT::f32)
+ Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
+ else if (VA.getLocVT() != MVT::i32) {
+ Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
+ DAG.getValueType(VA.getLocVT()));
+ Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
+ }
+ InVals.push_back(Arg);
+ continue;
+ }
+ } else {
+ // Try matching frame index.
+ assert(VA.isMemLoc());
+
+ EVT LocVT = VA.getLocVT();
+
+ // Create the frame index object for this incoming parameter.
+ int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8,
+ VA.getLocMemOffset(), true);
+
+ // Create the SelectionDAG nodes corresponding to a load
+ // from this parameter.
+ SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DL));
+ InVals.push_back(DAG.getLoad(LocVT, dl, Chain, FIN,
+ MachinePointerInfo::getFixedStack(MF, FI)));
+
+ }
+
+ SDValue ArgValue =
+ DAG.getLoad(VA.getValVT(), dl, Chain, Arg, MachinePointerInfo());
+ InVals.push_back(ArgValue);
+
+ unsigned ArgIndex = Ins[InIdx].OrigArgIndex;
+ assert(Ins[InIdx].PartOffset == 0);
+ while (i + 1 != e && Ins[InIdx + 1].OrigArgIndex == ArgIndex) {
+ CCValAssign &PartVA = ArgLocs[i + 1];
+ unsigned PartOffset = Ins[InIdx + 1].PartOffset;
+ SDValue Address = DAG.getMemBasePlusOffset(
+ ArgValue, TypeSize::getFixed(PartOffset), dl);
+ InVals.push_back(DAG.getLoad(PartVA.getValVT(), dl, Chain, Address,
+ MachinePointerInfo()));
+ ++i;
+ ++InIdx;
+ }
+ }
+
+ return Chain;
+}
+
+//===----------------------------------------------------------------------===//
+// RETURN LOWERING
+//===----------------------------------------------------------------------===//
+
+bool SuperHTargetLowering::CanLowerReturn(
+ CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
+ const Type *RetTy) const {
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
+ return CCInfo.CheckReturn(Outs, RetCC_SH);
+}
+
+SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals,
+ const SDLoc &dl, SelectionDAG &DAG) const {
+
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
+ *DAG.getContext());
+
+ // Analyze return values.
+ MachineFunction &MF = DAG.getMachineFunction();
+ CCInfo.AnalyzeReturn(Outs, RetCC_SH);
+
+ // Fill out values into registers.
+ SDValue Glue;
+ SmallVector<SDValue, 4> RetOps(1, Chain);
+ for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
+ CCValAssign &VA = RVLocs[i];
+
+ Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
+ Glue = Chain.getValue(1);
+ RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
+ }
+
+ // If function is naked, don't emit rts.
+ if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
+ return Chain;
+ }
+
+ // Update chain.
+ RetOps[0] = Chain;
+ if (Glue.getNode())
+ RetOps.push_back(Glue);
+
+ return DAG.getNode(SHISD::RET, dl, MVT::Other, RetOps);
+}
+
+SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const {
+ for(unsigned i = 0; i < CLI.Ins.size(); i++) {
+ auto VArg = CLI.getArgs()[i];
+ InVals.push_back(VArg.Node);
+ }
+
+ return CLI.Chain;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
new file mode 100644
index 0000000000000..4617740b75c6d
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -0,0 +1,47 @@
+//===-- SuperHISelLowering.h - SH DAG Lowering Interface --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that SuperH uses to lower LLVM code into a
+// selection DAG.
+//
+//===-----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHISELLOWERING_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHISELLOWERING_H
+
+#include "SuperH.h"
+#include "llvm/CodeGen/TargetLowering.h"
+
+namespace llvm {
+class SuperHSubtarget;
+
+class SuperHTargetLowering : public TargetLowering {
+ const SuperHSubtarget *Subtarget;
+
+ SDValue LowerFormalArguments(SDValue Chain,
+ CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ const SDLoc &dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const override;
+ SDValue LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals,
+ const SDLoc &dl, SelectionDAG &DAG) const override;
+ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
+ const Type *RetTy) const override;
+ SDValue LowerCall(CallLoweringInfo &/*CLI*/,
+ SmallVectorImpl<SDValue> &/*InVals*/) const override;
+public:
+ SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
+};
+
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td b/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
deleted file mode 100644
index d16a588da07a0..0000000000000
--- a/llvm/lib/Target/SuperH/SuperHInstrArithmetic.td
+++ /dev/null
@@ -1,77 +0,0 @@
-//===-- SuperHInstrArithmetic.td - SuperH Arithmetic Instructions -*- tablegen -*-==//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file describes all of the arithmetic instructions in the SuperH
-/// ISA.
-///
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Arithmetic Instructions
-//===----------------------------------------------------------------------===//
-
-let Namespace = "SH" in {
-
- // ADDITION
- def ADD_Rm_Rn : Op_Rm_Rn<0b0011000000001100, "add">;
- def ADD_imm_Rn : Op_Imm_Rn<0b0111000000000000, "add">;
- def ADDC_Rm_Rn : Op_Rm_Rn<0b0011000000001110, "addc">;
- def ADDV_Rm_Rn : Op_Rm_Rn<0b0011000000001111, "addv">;
-
- // SUBTRACTION
- def DT_Rn : Op_Rn<0b0100000000010000, "dt">;
- def NEG_Rm_Rn : Op_Rm_Rn<0b0110000000001011, "neg">;
- def NEGC_Rm_Rn : Op_Rm_Rn<0b0110000000001010, "negc">;
- def SUB_Rm_Rn : Op_Rm_Rn<0b0011000000001000, "sub">;
- def SUBC_Rm_Rn : Op_Rm_Rn<0b0011000000001010, "subc">;
- def SUBV_Rm_Rn : Op_Rm_Rn<0b0011000000001011, "subv">;
-
- // MULTIPLICATION
- def MUL_Rm_Rn : Op_Rm_Rn<0b0000000000000111, "mul.l">;
- def MULR_R0_Rn : Op_Rm_Rn<0b0100000010000000, "mulr">;
- def MULSW_Rm_Rn : Op_Rm_Rn<0b0010000000001111, "muls.w">;
- def MULUW_Rm_Rn : Op_Rm_Rn<0b0010000000001110, "mulu.w">;
- def DMULS_Rm_Rn : Op_Rm_Rn<0b0011000000001101, "dmuls.l">;
- def DMULU_Rm_Rn : Op_Rm_Rn<0b0011000000000101, "dmulu.l">;
-
- // DIVISION
- def DIV0S_Rm_Rn : Op_Rm_Rn<0b0010000000000111, "div0s">;
- def DIV0U : Op<0b0000000000011001, "div0u">;
- def DIV1_Rm_Rn : Op_Rm_Rn<0b0011000000000100, "div1">;
- def DIVS_R0_Rn : Op_R0_Rn<0b0100000010010100, "divs">;
- def DIVU_R0_Rn : Op_R0_Rn<0b0100000010000100, "divu">;
-
- // COMPARISON
- def CMPEQ_Imm_R0 : Op_Imm_R0<0b1000100000000000, "cmp/eq">;
- def CMPEQ_Rm_Rn : Op_Rm_Rn<0b0011000000000000, "cmp/eq">;
- def CMPHS_Rm_Rn : Op_Rm_Rn<0b0011000000000010, "cmp/hs">;
- def CMPGE_Rm_Rn : Op_Rm_Rn<0b0011000000000011, "cmp/ge">;
- def CMPHI_Rm_Rn : Op_Rm_Rn<0b0011000000000110, "cmp/hi">;
- def CMPGT_Rn : Op_Rn<0b0011000000000111, "cmp/gt">;
- def CMPPL_Rn : Op_Rn<0b0100000000010101, "cmp/pl">;
- def CMPPZ_Rn : Op_Rn<0b0100000000010001, "cmp/pz">;
- def CMPSTR_Rm_Rn : Op_Rm_Rn<0b0010000000001100, "cmp/str">;
-
- // INTEGER EXTENSION
- def EXTSB_Rm_Rn : Op_Rm_Rn<0b0110000000001110, "exts.b">;
- def EXTSW_Rm_Rn : Op_Rm_Rn<0b0110000000001111, "exts.w">;
- def EXTUB_Rm_Rn : Op_Rm_Rn<0b0110000000001100, "extu.b">;
- def EXTUW_Rm_Rn : Op_Rm_Rn<0b0110000000001101, "extu.w">;
-
- // LOGIC
- def AND_Rm_Rn : Op_Rm_Rn<0b0010000000001001, "and">;
- def AND_Imm_R0 : Op_Imm_R0<0b1100100100000000, "and">;
- def NOT_Rm_Rn : Op_Rm_Rn<0b0110000000000111, "not">;
- def OR_Rm_Rn : Op_Rm_Rn<0b0010000000001011, "or">;
- def OR_Imm_R0 : Op_Imm_R0<0b1100101100000000, "or">;
- def TST_Rm_Rn : Op_Rm_Rn<0b0010000000001000, "tst">;
- def TST_Imm_R0 : Op_Imm_R0<0b1100100000000000, "tst">;
- def XOR_Rm_Rn : Op_Rm_Rn<0b0010000000001010, "xor">;
- def XOR_Imm_R0 : Op_Imm_R0<0b1100101000000000, "xor">;
-}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrBranch.td b/llvm/lib/Target/SuperH/SuperHInstrBranch.td
deleted file mode 100644
index 3042301268c4e..0000000000000
--- a/llvm/lib/Target/SuperH/SuperHInstrBranch.td
+++ /dev/null
@@ -1,76 +0,0 @@
-//===-- SuperHInstrBranch.td - SuperH Branching Instructions -*- tablegen -*-==//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===-----------------------------------------------------------------------===//
-///
-/// \file
-/// This file describes all of the arithmetic instructions in the SuperH
-/// ISA.
-///
-//===-----------------------------------------------------------------------===//
-
-//===-----------------------------------------------------------------------===//
-// Instruction Class Templates
-//===-----------------------------------------------------------------------===//
-
-
-// disp + PC -> PC
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true in
-class BrOp_Disp8<bits<16> op, string opcodestr>
- : SHInstOP_D8<op, (outs), (ins disp8:$disp),
- !strconcat(opcodestr, " $disp")>;
-// disp + PC -> PC
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true in
-class BrOp_Disp12<bits<16> op, string opcodestr>
- : SHInstOP_D12<op, (outs), (ins disp12:$disp),
- !strconcat(opcodestr, " $disp")>;
-
-// disp + PC -> PC (Delayed)
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true, hasDelaySlot = true in
-class BrOpD_Disp8<bits<16> op, string opcodestr>
- : SHInstOP_D8<op, (outs), (ins disp8:$disp),
- !strconcat(opcodestr, " $disp")>;
-
-// Rm + PC -> PC
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true, isIndirectBranch = true in
-class BrOp_Rm<bits<16> op, string opcodestr>
- : SHInstOP_M4<op, (outs), (ins GPR:$Rm),
- !strconcat(opcodestr, " $Rm")>;
-// Rm -> PC
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = true, isIndirectBranch = true in
-class BrOp_Rmi<bits<16> op, string opcodestr>
- : SHInstOP_M4<op, (outs), (ins GPRMem:$Rm),
- !strconcat(opcodestr, " @$Rm")>;
-
-// CALL
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = true in
-class BrOpCall_Rmi<bits<16> op, string opcodestr>
- : SHInstOP_M4<op, (outs), (ins GPRMem:$Rm),
- !strconcat(opcodestr, " @$Rm")>;
-
-// RETURN
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isReturn = true in
-class BrOpRet<bits<16> op, string opcodestr>
- : SHInstOP<op, (outs), (ins), opcodestr>;
-
-
-//===-----------------------------------------------------------------------===//
-// Branch Instructions
-//===-----------------------------------------------------------------------===//
-
-let Namespace = "SH" in {
- def BF_Disp : BrOp_Disp8<0b1000101100000000, "bf">;
- def BFS_Disp : BrOpD_Disp8<0b1000111100000000, "bf/s">;
- def BT_Disp : BrOp_Disp8<0b1000100100000000, "bt">;
- def BTS_Disp : BrOpD_Disp8<0b1000110100000000, "bt/s">;
- def BRA_Disp : BrOp_Disp12<0b1010000000000000, "bra">;
- def BRAF_Rm : BrOp_Rm<0b0000000000100011, "braf">;
- def BSR_Disp : BrOp_Disp12<0b1011000000000000, "bsr">;
- def BSRF_Rm : BrOp_Rm<0b0000000000000011, "bsrf">;
- def JMP_Rmi : BrOp_Rmi<0b0100000000101011, "jmp">;
- def JSR_Rmi : BrOpCall_Rmi<0b0100000000001011, "jsr">;
- def RTS : BrOpRet<0b0000000000001011, "rts">;
-}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrData.td b/llvm/lib/Target/SuperH/SuperHInstrData.td
deleted file mode 100644
index 97257cff43d88..0000000000000
--- a/llvm/lib/Target/SuperH/SuperHInstrData.td
+++ /dev/null
@@ -1,172 +0,0 @@
-//===-- SuperHInstrData.td - SuperH Data Transfer Instructions -*- tablegen -*-==//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file describes all of the data transfer instructions in the SuperH
-/// ISA.
-///
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Instruction Class Templates
-//===----------------------------------------------------------------------===//
-
-// LOAD
-let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
-
- // X -> Rn
- class LdOp_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4<op, (outs GPR:$Rn), (ins),
- !strconcat(opcodestr, " $Rn")>;
-
- // Rm -> Rn
- class LdOp_Rm_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
- !strconcat(opcodestr, " $Rm, $Rn")>;
-
- // #imm -> sign extension -> Rn
- class LdOp_Imm_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_I8<op, (outs GPR:$Rn), (ins imm8:$imm),
- !strconcat(opcodestr, " $imm, $Rn")>;
-
- // (disp) -> R0
- class LdOp_DispPC_R0<bits<16> op, string opcodestr>
- : SHInstOP_D8<op, (outs), (ins disp8:$disp),
- !strconcat(opcodestr, " @($disp,pc),R0")>;
-
- // (disp) -> [sign extension] -> Rn
- class LdOp_DispPC_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_D8<op, (outs GPR:$Rn), (ins disp8:$disp),
- !strconcat(opcodestr, " @($disp,pc), $Rn")>;
-
- // (Rm) -> [sign extension] -> Rn
- class LdOp_Rmi_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPRMem:$Rm),
- !strconcat(opcodestr, " @$Rm, $Rn")>;
-
- // (Rm) -> [sign extension] -> Rn, Rm+1 -> Rm
- class LdOp_Rminci_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPRMem:$Rm),
- !strconcat(opcodestr, " @$Rm+, $Rn")>;
-
- // (disp + Rm) -> [sign extension] -> R0
- class LdOp_DispRm_R0<bits<16> op, string opcodestr>
- : SHInstOP_M4_D4<op, (outs), (ins disp4:$disp, GPR:$Rm),
- !strconcat(opcodestr, " @($disp, $Rm), R0")>;
-
- // (disp + Rm) -> [sign extension] -> Rn
- class LdOp_DispRm_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4_D4<op, (outs GPR:$Rn), (ins disp4:$disp, GPR:$Rm),
- !strconcat(opcodestr, " @($disp, $Rm), $Rn")>;
-
- // (R0 + Rm) -> [sign extension] -> Rn
- class LdOp_RelR0Rm_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
- !strconcat(opcodestr, " @(R0, $Rm), $Rn")>;
-
- // (disp + GBR) -> [sign extension] -> R0
- class LdOp_DispGBR_R0<bits<16> op, string opcodestr>
- : SHInstOP_D8<op, (outs), (ins disp8:$disp),
- !strconcat(opcodestr, " @($disp, gbr),R0")>;
-}
-
-// STORE
-let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
-
-
- // Rm -> [sign extension] -> (Rn)
- class StOp_Rm_Rni<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
- !strconcat(opcodestr, " $Rm, @$Rn")>;
-
- // Rn-1 -> Rn, Rm -> [sign extension] -> (Rn)
- class StOp_Rm_Rndeci<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPRMem:$Rn), (ins GPR:$Rm),
- !strconcat(opcodestr, " $Rm, @-$Rn")>;
-
- // R0 -> [sign extension] -> (disp + Rn)
- class StOp_R0_DispRn<bits<16> op, string opcodestr>
- : SHInstOP_N4_D4<op, (outs disp4:$disp, GPR:$Rn), (ins),
- !strconcat(opcodestr, " R0, @( $disp, $Rn )")>;
-
- // Rm -> [sign extension] -> (disp + Rn)
- class StOp_Rm_DispRn<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4_D4<op, (outs disp4:$disp, GPR:$Rn), (ins GPR:$Rm),
- !strconcat(opcodestr, " $Rm, @( $disp, $Rn )")>;
-
- // Rm -> (R0 + Rn)
- class StOp_Rm_RelR0Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
- !strconcat(opcodestr, " $Rm, @(R0, $Rn)")>;
-
- // R0 -> (disp + GBR)
- class StOp_R0_DispGBR<bits<16> op, string opcodestr>
- : SHInstOP_D8<op, (outs disp8:$disp), (ins),
- !strconcat(opcodestr, " R0, @($disp, gbr)")>;
-}
-
-
-//===----------------------------------------------------------------------===//
-// Instructions
-//===----------------------------------------------------------------------===//
-
-let Namespace = "SH" in {
-
- // LOADS
- def MOV_Rm_Rn : LdOp_Rm_Rn<0b0110000000000011, "mov">;
- def MOVA_dispPC_R0 : LdOp_DispPC_R0<0b1100011100000000, "mova">;
- def MOVW_dispPC_Rn : LdOp_DispPC_Rn<0b1001000000000000, "mov.w">;
- def MOVL_dispPC_Rn : LdOp_DispPC_Rn<0b1101000000000000, "mov.l">;
- def MOVB_Rmi_Rn : LdOp_Rmi_Rn<0b0110000000000000, "mov.b">;
- def MOVW_Rmi_Rn : LdOp_Rmi_Rn<0b0110000000000001, "mov.w">;
- def MOVL_Rmi_Rn : LdOp_Rmi_Rn<0b0110000000000010, "mov.l">;
- def MOVB_Rminci_Rn : LdOp_Rminci_Rn<0b0110000000000100, "mov.b">;
- def MOVW_Rminci_Rn : LdOp_Rminci_Rn<0b0110000000000101, "mov.w">;
- def MOVL_Rminci_Rn : LdOp_Rminci_Rn<0b0110000000000110, "mov.l">;
- def MOVB_dispRm_R0 : LdOp_DispRm_R0<0b1000010000000000, "mov.b">;
- def MOVW_dispRm_R0 : LdOp_DispRm_R0<0b1000010100000000, "mov.w">;
- def MOVL_dispRm_Rn : LdOp_DispRm_Rn<0b0101000000000000, "mov.l">;
- def MOVB_RelR0Rm_Rn : LdOp_RelR0Rm_Rn<0b0000000000001100, "mov.b">;
- def MOVW_RelR0Rm_Rn : LdOp_RelR0Rm_Rn<0b0000000000001101, "mov.w">;
- def MOVL_RelR0Rm_Rn : LdOp_RelR0Rm_Rn<0b0000000000001110, "mov.l">;
- def MOVB_dispGBR_R0 : LdOp_DispGBR_R0<0b1100010000000000, "mov.b">;
- def MOVW_dispGBR_R0 : LdOp_DispGBR_R0<0b1100010100000000, "mov.w">;
- def MOVL_dispGBR_R0 : LdOp_DispGBR_R0<0b1100011000000000, "mov.l">;
-
- def MOVRT_Rn : LdOp_Rn<0b0000000000111001, "movrt">;
- def MOVT_Rn : LdOp_Rn<0b0000000000101001, "movt">;
-
- // STORES
- def MOV_imm_Rn : LdOp_Imm_Rn<0b1110000000000000, "mov">;
- def MOVB_Rm_Rni : StOp_Rm_Rni<0b0010000000000000, "mov.b">;
- def MOVW_Rm_Rni : StOp_Rm_Rni<0b0010000000000001, "mov.w">;
- def MOVL_Rm_Rni : StOp_Rm_Rni<0b0010000000000010, "mov.l">;
- def MOVB_Rm_Rndeci : StOp_Rm_Rndeci<0b0010000000000100, "mov.b">;
- def MOVW_Rm_Rndeci : StOp_Rm_Rndeci<0b0010000000000101, "mov.w">;
- def MOVL_Rm_Rndeci : StOp_Rm_Rndeci<0b0010000000000110, "mov.l">;
- def MOVB_R0_dispRn : StOp_R0_DispRn<0b1000000000000000, "mov.b">;
- def MOVW_R0_dispRn : StOp_R0_DispRn<0b1000000100000000, "mov.w">;
- def MOVL_Rm_dispRn : StOp_Rm_DispRn<0b0001000000000000, "mov.l">;
- def MOVB_Rm_RelR0Rn : StOp_Rm_RelR0Rn<0b0000000000000100, "mov.b">;
- def MOVW_Rm_RelR0Rn : StOp_Rm_RelR0Rn<0b0000000000000101, "mov.w">;
- def MOVL_Rm_RelR0Rn : StOp_Rm_RelR0Rn<0b0000000000000110, "mov.l">;
- def MOVB_R0_dispGBR : StOp_R0_DispGBR<0b1100000000000000, "mov.b">;
- def MOVW_R0_dispGBR : StOp_R0_DispGBR<0b1100000100000000, "mov.w">;
- def MOVL_R0_dispGBR : StOp_R0_DispGBR<0b1100001000000000, "mov.l">;
-
- // OTHER
- def NOTT : Op<0b0000000001101000, "nott">;
- def SWAPB_Rm_Rn : Op_Rm_Rn<0b0110000000001000, "swap.b">;
- def SWAPW_Rm_Rn : Op_Rm_Rn<0b0110000000001001, "swap.w">;
- def XTRCT_Rm_Rn : Op_Rm_Rn<0b0010000000001101, "xtrct">;
-}
-
-// LOAD ALIASES
-def MOVA_Disp_R0 : InstAlias<"mova $disp, R0", (MOVA_dispPC_R0 disp8:$disp), 0>;
-def MOVW_Disp_Rn : InstAlias<"mov.w $disp, $Rn", (MOVW_dispPC_Rn GPR:$Rn, disp8:$disp), 0>;
-def MOVL_Disp_Rn : InstAlias<"mov.l $disp, $Rn", (MOVL_dispPC_Rn GPR:$Rn, disp8:$disp), 0>;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index dbe83b764fbee..442a543807aa3 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -38,63 +38,69 @@
//
//===----------------------------------------------------------------------===//
-// Base of all 16-bit SuperH instructions
-class SHInst <dag outs, dag ins, string asmstr, list<dag> pattern> : Instruction {
- field bits<16> Inst;
- field bits<16> SoftFail = 0;
-
- bits<16> Opcode = 0;
-
+class SHInst<dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : Instruction {
let Namespace = "SH";
dag OutOperandList = outs;
dag InOperandList = ins;
let AsmString = asmstr;
let Pattern = pattern;
+}
+
+
+// Base of all 16-bit SuperH instructions
+class SHInst16<dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst<outs, ins, asmstr, pattern> {
+ field bits<16> SoftFail = 0;
+ field bits<16> Inst;
+ bits<16> Opcode = 0;
let Size = 2;
}
-// SuperH Psuedo Instruction
+class SHInst32<dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst<outs, ins, asmstr, pattern> {
+ field bits<16> SoftFail = 0;
+ field bits<16> Inst;
+ bits<32> Opcode = 0;
+ let Size = 4;
+}
+
+// SuperH Pseudo Instruction
+// These are not real instructions but are expanded to real instructions
+// in later passes implemented in C++.
class SHPseudo<dag outs, dag ins, string asmstr="; error: this should not be emitted", list<dag> pattern = []>
: SHInst<outs, ins, asmstr, pattern> {
- let isPseudo = 1;
let isCodeGenOnly = 1;
+ let isPseudo = 1;
}
-//===----------------------------------------------------------------------===//
-// Instruction Formats
-//===----------------------------------------------------------------------===//
-class SHInstOP_N4_I8 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
- // Opcode
- let Opcode = opcode;
- let Inst{15-12} = Opcode{15-12};
- // Operands
- bits<4> Rn;
- bits<8> imm;
- let Inst{11-8} = Rn;
- let Inst{7-0} = imm;
-}
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+// Instruction Formats
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-class SHInstOP_N4_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
-
+//===----------------------------------------------------------------------===//
+// No-operand Instruction
+// <opopopopopopopop>
+//===----------------------------------------------------------------------===//
+class Inst<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
- let Inst{15-12} = Opcode{15-12};
-
- // Operands
- bits<4> Rn;
- bits<8> disp;
- let Inst{11-8} = Rn;
- let Inst{7-0} = disp;
+ let Inst = Opcode;
}
-class SHInstOP_N4_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// Register -> Register Instruction
+// <opop|rnrn|rmrm|opop>
+//===----------------------------------------------------------------------===//
+class InstRmRn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
@@ -108,36 +114,65 @@ class SHInstOP_N4_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
let Inst{7-4} = Rm;
}
-class SHInstOP_N4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// (Any) -> Register Instruction
+// <opop|rnrn|opopopop>
+//===----------------------------------------------------------------------===//
+class InstRn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
let Inst{15-8} = Opcode{15-8};
+ let Inst{7-0} = Opcode{7-0};
// Operands
bits<4> Rn;
- bits<4> disp;
- let Inst{7-4} = Rn;
- let Inst{0-3} = disp;
+ let Inst{11-8} = Rn;
}
-class SHInstOP_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// Register -> (Any) Instruction
+// <opop|rmrm|opopopop>
+//===----------------------------------------------------------------------===//
+class InstRm<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
let Inst{15-8} = Opcode{15-8};
+ let Inst{7-0} = Opcode{7-0};
// Operands
bits<4> Rm;
- bits<4> disp;
- let Inst{7-4} = Rm;
- let Inst{0-3} = disp;
+ let Inst{11-8} = Rm;
+}
+
+//===----------------------------------------------------------------------===//
+// Immediate -> Register Instruction
+// <opop|rnrn|iiiiiiii>
+//===----------------------------------------------------------------------===//
+class InstI8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
+
+ // Opcode
+ let Opcode = opcode;
+ let Inst{15-12} = Opcode{15-12};
+
+ // Operands
+ bits<4> Rn;
+ bits<8> imm;
+ let Inst{11-8} = Rn;
+ let Inst{7-0} = imm;
}
-class SHInstOP_N4_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// (disp:8) -> Register Instruction
+// <opop|rnrn|dddddddd>
+//===----------------------------------------------------------------------===//
+class InstD8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
+
// Opcode
let Opcode = opcode;
@@ -145,80 +180,111 @@ class SHInstOP_N4_M4_D4 <bits<16> opcode, dag outs, dag ins, string asmstr>
// Operands
bits<4> Rn;
- bits<4> Rm;
- bits<4> disp;
+ bits<8> disp;
let Inst{11-8} = Rn;
- let Inst{7-4} = Rm;
- let Inst{0-3} = disp;
+ let Inst{7-0} = disp;
}
-class SHInstOP_D12 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// (Register + disp:4) -> Register Instruction
+// <opop|rnrn|rmrm|dddd>
+//===----------------------------------------------------------------------===//
+class InstRmD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
let Inst{15-12} = Opcode{15-12};
// Operands
- bits<12> disp;
- let Inst{11-0} = disp;
+ bits<4> Rn;
+ bits<4> Rm;
+ bits<4> disp;
+ let Inst{11-8} = Rn;
+ let Inst{7-4} = Rm;
+ let Inst{0-3} = disp;
}
-class SHInstOP_D8 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// (disp:4) -> Register Instruction
+// <opopopop|rnrn|dddd>
+//===----------------------------------------------------------------------===//
+class InstD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
let Inst{15-8} = Opcode{15-8};
// Operands
- bits<8> disp;
- let Inst{7-0} = disp;
+ bits<4> Rn;
+ bits<4> disp;
+ let Inst{7-4} = Rn;
+ let Inst{0-3} = disp;
}
-class SHInstOP_I8 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// (disp:4 + Register) -> Reserved Register Instruction
+// <opopopop|rmrm|dddd>
+//===----------------------------------------------------------------------===//
+class InstD4RmRr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
let Inst{15-8} = Opcode{15-8};
// Operands
- bits<8> imm;
- let Inst{7-0} = imm;
+ bits<4> Rm;
+ bits<4> disp;
+ let Inst{7-4} = Rm;
+ let Inst{0-3} = disp;
}
-class SHInstOP_N4 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// (disp:8) Instruction
+// <opopopop|dddddddd>
+//===----------------------------------------------------------------------===//
+class InstD8Rr<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
let Inst{15-8} = Opcode{15-8};
- let Inst{7-0} = Opcode{7-0};
// Operands
- bits<4> Rn;
- let Inst{11-8} = Rn;
+ bits<8> disp;
+ let Inst{7-0} = disp;
}
-class SHInstOP_M4 <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// (imm:8) Instruction
+// <opopopop|iiiiiiii>
+//===----------------------------------------------------------------------===//
+class InstI8Rr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
let Inst{15-8} = Opcode{15-8};
- let Inst{7-0} = Opcode{7-0};
// Operands
- bits<4> Rm;
- let Inst{11-8} = Rm;
+ bits<8> imm;
+ let Inst{7-0} = imm;
}
-class SHInstOP <bits<16> opcode, dag outs, dag ins, string asmstr>
- : SHInst<outs, ins, asmstr, []> {
+//===----------------------------------------------------------------------===//
+// (disp:12) Instruction
+// <opop|dddddddddddd>
+//===----------------------------------------------------------------------===//
+class InstD12Rr<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+ : SHInst16<outs, ins, asmstr, pattern> {
// Opcode
let Opcode = opcode;
- let Inst = Opcode;
-}
+ let Inst{15-12} = Opcode{15-12};
+ // Operands
+ bits<12> disp;
+ let Inst{11-0} = disp;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index a4cc7447e2e48..303048a47389a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "SuperHInstrInfo.h"
+#include "SuperHRegisterInfo.h"
#include "SuperHSubtarget.h"
#include "SuperHTargetMachine.h"
#include "SuperH.h"
@@ -28,8 +29,23 @@ using namespace llvm;
#define GET_INSTRINFO_CTOR_DTOR
#include "SuperHGenInstrInfo.inc"
-void SuperHInstrInfo::anchor() {}
-
SuperHInstrInfo::SuperHInstrInfo(const SuperHSubtarget &ST)
: SuperHGenInstrInfo(ST, RI, SH::ADJCALLSTACKDOWN, SH::ADJCALLSTACKUP),
- RI(ST), Subtarget(ST) { }
\ No newline at end of file
+ RI(ST), Subtarget(ST) { }
+
+void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI, const DebugLoc &DL,
+ Register DestReg, Register SrcReg, bool KillSrc,
+ bool RenamableDest,
+ bool RenamableSrc) const {
+
+ // If the targets are GPR registers, use MOV Rm, Rn.
+ if (SH::GPRRegClass.contains(DestReg, SrcReg)) {
+ BuildMI(MBB, MI, DL, get(SH::MOVRmRn), DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc));
+ return;
+ }
+
+ // Otherwise this is not possible.
+ llvm_unreachable("Impossible reg-to-reg copy");
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 458bde9bfc64a..65231455267a9 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -26,10 +26,23 @@ namespace llvm {
class SuperHInstrInfo : public SuperHGenInstrInfo {
const SuperHRegisterInfo RI;
const SuperHSubtarget &Subtarget;
- virtual void anchor();
+
public:
explicit SuperHInstrInfo(const SuperHSubtarget &STI);
+
+ /// 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).
+ const SuperHRegisterInfo &getRegisterInfo() const { return RI; }
+
+ void copyPhysReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI, const DebugLoc &DL,
+ Register DestReg, Register SrcReg, bool KillSrc,
+ bool RenamableDest = false,
+ bool RenamableSrc = false) const override;
};
+
+const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
}
#endif // end LLVM_LIB_TARGET_SUPERH_SUPERHINSTRINFO_H
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 9209450d1a196..8bd12bd5cfcbb 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -42,27 +42,27 @@ def ptr_op : RegisterOperand<sh_ptr_rc> {
// SuperH Type Profiles
//===----------------------------------------------------------------------===//
-def SHSDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
-def SHSDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
-def SHSDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
-def SHSDT_Ret : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
+def SHSDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+def SHSDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+def SHSDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
//===----------------------------------------------------------------------===//
-// Nodes
+// SuperH Specific Nodes
//===----------------------------------------------------------------------===//
def SHCallSeqStart : SDNode<"ISD::CALLSEQ_START", SHSDT_CallSeqStart,
- [SDNPHasChain, SDNPOutGlue]>;
+ [SDNPHasChain, SDNPOutGlue]>;
def SHCallSeqEnd : SDNode<"ISD::CALLSEQ_END", SHSDT_CallSeqEnd,
- [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
def SHCall : SDNode<"SHISD::CALL", SHSDT_Call,
- [SDNPHasChain, SDNPOutGlue,
+ [SDNPHasChain, SDNPOutGlue,
SDNPOptInGlue, SDNPVariadic]>;
-def SHRet : SDNode<"SHISD::RET", SHSDT_Ret,
- [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
+def SHRet : SDNode<"SHISD::RET", SDTNone,
+ [SDNPHasChain, SDNPOptInGlue,
+ SDNPVariadic]>;
//===----------------------------------------------------------------------===//
// Operand Classes
@@ -89,9 +89,9 @@ class SHDispClass<int width> : SHOpClass<"Disp" # width> {
}
// Memory Ops
-class SHMemClass : SHOpClass<"Mem"> {
- let PredicateMethod = "isMem";
- let RenderMethod = "addMemOperands";
+def SHMemClass : SHOpClass<"Mem"> {
+ let PredicateMethod = "isMem";
+ let RenderMethod = "addMemOperands";
}
//===----------------------------------------------------------------------===//
@@ -103,25 +103,19 @@ class SHImmOp<int width, ValueType vt>
: Operand<vt> {
let ParserMatchClass = SHImmClass<width>;
let OperandType = "OPERAND_IMMEDIATE";
- let MCOperandPredicate = [{
- int64_t Imm;
- if (MCOp.evaluateAsConstantImm(Imm))
- return isInt<#width>(Imm);
- return MCOp.isBareSymbolRef();
- }];
+ let MCOperandPredicate = [{int64_t Imm; return MCOp.evaluateAsConstantImm(Imm) ? isInt<}] # width # [{>(Imm) : false;}];
}
-
-def imm8 : SHImmOp<8, i8>;
+def imm8 : SHImmOp<8, i32>, ImmLeaf<i32, [{ return isInt<8>(Imm); }]>;
// Displacement
class SHDispOp<int width, ValueType vt>
- : Operand<vt> {
+ : Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
let ParserMatchClass = SHDispClass<width>;
let OperandType = "OPERAND_IMMEDIATE";
let MCOperandPredicate = [{
int64_t Imm;
if (MCOp.evaluateAsConstantImm(Imm))
- return isInt<#width>(Imm);
+ return isUInt<#width>(Imm);
return MCOp.isBareSymbolRef();
}];
}
@@ -134,67 +128,313 @@ def disp12 : SHDispOp<12, i16>;
// Memory
class SHMemRegOp<RegisterClass regClass>
: RegisterOperand<regClass> {
- let ParserMatchClass = SHMemClass<>;
+ let ParserMatchClass = SHMemClass;
let OperandType = "OPERAND_MEMORY";
}
def GPRMem : SHMemRegOp<GPR>;
+// Memory Indirect (Register + Register)
+def MemRRI : Operand<iPTR> {
+ let ParserMatchClass = SHMemClass;
+ let OperandType = "OPERAND_MEMORY";
+ let MIOperandInfo = (ops GPR, GPR);
+}
+
+// Memory Indirect (Register + Disp)
+def MemRD : Operand<iPTR> {
+ let ParserMatchClass = SHMemClass;
+ let OperandType = "OPERAND_MEMORY";
+ let MIOperandInfo = (ops GPR, disp8);
+}
+
+// Memory Indirect (GBR + disp)
+def MemGBRI : Operand<iPTR> {
+ let ParserMatchClass = SHMemClass;
+ let OperandType = "OPERAND_MEMORY";
+ let MIOperandInfo = (ops R_GBR, disp8);
+}
+
+// Memory Indirect (R0 + disp)
+def MemR0I : Operand<iPTR> {
+ let ParserMatchClass = SHMemClass;
+ let OperandType = "OPERAND_MEMORY";
+ let MIOperandInfo = (ops R_R0, disp8);
+}
+
+// Addressing mode pattern reg+disp
+let WantsRoot = true in
+def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+// Instruction Definitions
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Data Transfer Instructions
+//===----------------------------------------------------------------------===//
+
+// mov Rm, Rn
+let hasSideEffects = 0 in
+def MOVRmRn : InstRmRn<0b0110000000000011,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov $Rm,$Rn",
+ []>;
+
+// mov #imm:8, Rn
+let hasSideEffects = 0 in
+def MOVI8Rn : InstI8Rn<0b1110000000000000,
+ (outs GPR:$Rn), (ins imm8:$imm),
+ "mov #$imm,$Rn",
+ [(set i32:$Rn, imm8:$imm)]>;
+
+
+// mova @(disp,PC), R0
+
+
+//===----------------------------------------------------------------------===//
+// Load Instructions
+//===----------------------------------------------------------------------===//
+
+// Indirect Memory -> Register Load
+let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
+ def MOVBRmiRn : InstRmRn<0b0110000000000000,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.b @$Rm,$Rn",
+ [(set i32:$Rn, (sextloadi8 i32:$Rm))]>;
+
+ def MOVWRmiRn : InstRmRn<0b0110000000000001,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.w @$Rm,$Rn",
+ [(set i32:$Rn, (sextloadi16 i32:$Rm))]>;
+
+ def MOVLRmiRn : InstRmRn<0b0110000000000010,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.l @$Rm,$Rn",
+ [(set i32:$Rn, (load i32:$Rm))]>;
+}
+
+// Indirect Memory w/ Displacement -> Register Load
+let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
+ def MOVLD4RmiRn : InstRmD4Rn<0b0101000000000000,
+ (outs GPRMem:$Rn), (ins GPR:$Rm, disp4:$disp),
+ "mov.l @($disp, $Rm),$Rn",
+ []>;
+
+ // "mov.l", [(set i32:$Rn, (load addr:$disp))]>;
+}
+
+
//===----------------------------------------------------------------------===//
-// Instruction Class Templates
+// Store Instructions
//===----------------------------------------------------------------------===//
-let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
+// Register -> Indirect Memory Store
+let hasSideEffects = 0, mayStore = 1 in {
+ def MOVBRmRni : InstRmRn<0b0010000000000000,
+ (outs), (ins GPRMem:$Rn, GPR:$Rm),
+ "mov.b $Rm,@$Rn",
+ [(truncstorei8 GPRMem:$Rn, i32:$Rm)]>;
+
+ def MOVWRmRni : InstRmRn<0b0010000000000001,
+ (outs), (ins GPRMem:$Rn, GPR:$Rm),
+ "mov.w $Rm,@$Rn",
+ [(truncstorei16 GPRMem:$Rn, i32:$Rm)]>;
+
+ def MOVLRmRni : InstRmRn<0b0010000000000010,
+ (outs), (ins GPRMem:$Rn, GPR:$Rm),
+ "mov.l $Rm,@$Rn",
+ [(store GPRMem:$Rn, i32:$Rm)]>;
+}
- // No-arg instruction
- class Op<bits<16> op, string opcodestr>
- : SHInstOP<op, (outs), (ins), opcodestr>;
+//===----------------------------------------------------------------------===//
+// Arithmetic Instructions
+//===----------------------------------------------------------------------===//
- // Rn
- class Op_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4<op, (outs GPR:$Rn), (ins),
- !strconcat(opcodestr, " $Rn")>;
+//
+// ADDITION
+//
+let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+
+ // add Rm, Rn
+ def ADDRmRn : InstRmRn<0b0011000000001100,
+ (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ "add $Rm,$Rn",
+ [(set i32:$Rn, (add i32:$src, i32:$Rm))]>;
+
+ // add imm:8, Rn
+ def ADDI8Rn : InstI8Rn<0b0011000000001100,
+ (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
+ "add #$imm,$Rn",
+ [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
+
+ // addc Rm, Rn
+ let Defs = [SR], Uses = [SR] in
+ def ADDCRmRn : InstRmRn<0b0011000000001110,
+ (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ "addc $Rm,$Rn",
+ [(set i32:$Rn, (adde i32:$src, i32:$Rm))]>;
+
+ // addv Rm, Rn
+ let Defs = [SR] in
+ def ADDVRmRn : InstRmRn<0b0011000000001111,
+ (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ "addv $Rm,$Rn",
+ [(set i32:$Rn, (addc i32:$src, i32:$Rm))]>;
- // R0 -> (OP) -> Rn
- class Op_R0_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4<op, (outs GPR:$Rn), (ins),
- !strconcat(opcodestr, " r0,$Rn")>;
+}
- // Rm -> (OP) -> Rn
- class Op_Rm_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_M4<op, (outs GPR:$Rn), (ins GPR:$Rm),
- !strconcat(opcodestr, " $Rm,$Rn")>;
+//
+// SUBTRACTION
+//
+let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+
+ // sub Rm, Rn
+ def SUBRmRn : InstRmRn<0b0011000000001000,
+ (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ "sub $Rm,$Rn",
+ [(set i32:$Rn, (sub i32:$src, i32:$Rm))]>;
+
+ // subc Rm, Rn
+ let Defs = [SR], Uses = [SR] in
+ def SUBCRmRn : InstRmRn<0b0011000000001010,
+ (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ "subc $Rm,$Rn",
+ [(set i32:$Rn, (sube i32:$src, i32:$Rm))]>;
+
+ // subv Rm, Rn
+ let Defs = [SR] in
+ def SUBVRmRn : InstRmRn<0b0011000000001011,
+ (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ "subv $Rm,$Rn",
+ [(set i32:$Rn, (subc i32:$src, i32:$Rm))]>;
+
+ // dt Rn
+ let Defs = [SR] in
+ def DTRmRn : InstRn<0b0011000000001000,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "dt $Rn",
+ [(set i32:$Rn, (sub i32:$src, -1))]>;
+}
- // imm -> (OP) -> Rn
- class Op_Imm_Rn<bits<16> op, string opcodestr>
- : SHInstOP_N4_I8<op, (outs GPR:$Rn), (ins imm8:$imm),
- !strconcat(opcodestr, " $imm,$Rn")>;
+//
+// NEGATION
+//
+let hasSideEffects = 0 in {
+
+ // neg Rm, Rn
+ def NEGRmRn : InstRmRn<0b0110000000001011,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "neg $Rm,$Rn",
+ [(set i32:$Rn, (ineg i32:$Rm))]>;
+
+ // negc Rm, Rn
+ let Defs = [SR], Uses = [SR] in
+ def NEGCRmRn : InstRmRn<0b0110000000001010,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "negc $Rm,$Rn",
+ [(set i32:$Rn, (ineg i32:$Rm))]>;
- // imm -> (OP) -> Rn
- class Op_Imm_R0<bits<16> op, string opcodestr>
- : SHInstOP_I8<op, (outs), (ins imm8:$imm),
- !strconcat(opcodestr, " $imm,R0")>;
}
+//
+// MULTIPLY
+//
+let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+
+ // mul.l Rm, Rn
+ let Defs = [MACL] in
+ def MULRmRn : InstRmRn<0b0000000000000111,
+ (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ "mul.l $Rm,$Rn",
+ []>;
+
+ // mulr Rm, Rn
+ let Uses = [R0] in
+ def MULRR0Rn : InstRn<0b0100000010000000,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "mulr R0,$Rn",
+ []>;
+
+}
//===----------------------------------------------------------------------===//
-// Basic Instructions
+// Branch Instructions
//===----------------------------------------------------------------------===//
-// NOP instruction, does nothing.
-def NOP : Op<0b0000000000001001, "nop">;
+// TODO: Port these to the updated way.
+// def BF_Disp : BrOp_Disp8<0b1000101100000000, "bf">;
+// def BFS_Disp : BrOpD_Disp8<0b1000111100000000, "bf/s">;
+// def BT_Disp : BrOp_Disp8<0b1000100100000000, "bt">;
+// def BTS_Disp : BrOpD_Disp8<0b1000110100000000, "bt/s">;
+// def BRA_Disp : BrOp_Disp12<0b1010000000000000, "bra">;
+// def BRAF_Rm : BrOp_Rm<0b0000000000100011, "braf">;
+// def BSR_Disp : BrOp_Disp12<0b1011000000000000, "bsr">;
+// def BSRF_Rm : BrOp_Rm<0b0000000000000011, "bsrf">;
+// def JMP_Rmi : BrOp_Rmi<0b0100000000101011, "jmp">;
+
//===----------------------------------------------------------------------===//
-// Subsystems
+// Call Instructions
//===----------------------------------------------------------------------===//
-include "SuperHInstrData.td"
-include "SuperHInstrArithmetic.td"
-include "SuperHInstrBranch.td"
+let isCall = 1 in {
+ let Uses = [GBR] in
+ def JSRRmi : InstRm<0b0100000000001011,
+ (outs), (ins GPRMem:$Rm),
+ "jsr @$Rm",
+ [(SHCall GPRMem:$Rm)]>;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Return Instructions
+//===----------------------------------------------------------------------===//
+
+let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
+ def RTS : Inst<0b0000000000001011,
+ (outs), (ins),
+ "rts",
+ []>;
+}
+
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Control Instructions
+//===----------------------------------------------------------------------===//
+
+// nop
+let hasSideEffects = 1 in
+def NOP : Inst<0b0000000000001001, (outs), (ins), "nop", []>;
+
+// sleep
+let hasSideEffects = 1 in
+def SLEEP : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
+
+
+
//===----------------------------------------------------------------------===//
// Pseudo instructions
//===----------------------------------------------------------------------===//
+// Helper instruction for mapping frame indices to relative frame pointer
+// offsets.
+let Defs = [SR], hasSideEffects = 0 in
+def SHFrmIdx : SHPseudo<(outs GPR:$dst), (ins GPR:$src, disp12:$src2)>;
+
let Defs = [R0], Uses = [R0] in {
def ADJCALLSTACKDOWN : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
"!ADJCALLSTACKDOWN $amt1, $amt2",
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
new file mode 100644
index 0000000000000..9e3198be7dddd
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -0,0 +1,78 @@
+//===-- SuperHMCInstLower.cpp - Lower MachineInstr to MCInst ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHMCInstLower.h"
+#include "SuperHSubtarget.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+
+
+namespace llvm {
+
+MCOperand
+SuperHMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
+ const SuperHSubtarget &Subtarget) const {
+ const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
+ return MCOperand::createExpr(Expr);
+}
+
+void SuperHMCInstLower::lowerInstruction(const MachineInstr &MI,
+ MCInst &OutMI) const {
+ auto &Subtarget = MI.getParent()->getParent()->getSubtarget<SuperHSubtarget>();
+
+ OutMI.setOpcode(MI.getOpcode());
+ for (MachineOperand const &MO : MI.operands()) {
+ MCOperand MCOp;
+
+ switch (MO.getType()) {
+ default:
+ MI.print(errs());
+ 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_GlobalAddress:
+ MCOp =
+ lowerSymbolOperand(MO, Printer.getSymbol(MO.getGlobal()), Subtarget);
+ break;
+ case MachineOperand::MO_ExternalSymbol:
+ MCOp = lowerSymbolOperand(
+ MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()), Subtarget);
+ break;
+ case MachineOperand::MO_MachineBasicBlock:
+ MCOp = MCOperand::createExpr(
+ MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
+ break;
+ case MachineOperand::MO_RegisterMask:
+ continue;
+ case MachineOperand::MO_BlockAddress:
+ MCOp = lowerSymbolOperand(
+ MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()), Subtarget);
+ break;
+ case MachineOperand::MO_JumpTableIndex:
+ MCOp = lowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()),
+ Subtarget);
+ break;
+ case MachineOperand::MO_ConstantPoolIndex:
+ MCOp = lowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()),
+ Subtarget);
+ break;
+ }
+
+ OutMI.addOperand(MCOp);
+ }
+}
+
+} // namespace llvm
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.h b/llvm/lib/Target/SuperH/SuperHMCInstLower.h
new file mode 100644
index 0000000000000..d5d86fee61066
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.h
@@ -0,0 +1,43 @@
+//===-- SuperHMCInstLower.h - Lower MachineInstr to MCInst ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPERH_MCINST_LOWER_H
+#define LLVM_SUPERH_MCINST_LOWER_H
+
+#include "SuperHSubtarget.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+class AsmPrinter;
+class MachineInstr;
+class MachineOperand;
+class MCContext;
+class MCInst;
+class MCOperand;
+class MCSymbol;
+
+/// Lowers `MachineInstr` objects into `MCInst` objects.
+class SuperHMCInstLower {
+public:
+ SuperHMCInstLower(MCContext &Ctx, AsmPrinter &Printer)
+ : Ctx(Ctx), Printer(Printer) {}
+
+ /// Lowers a `MachineInstr` into a `MCInst`.
+ void lowerInstruction(const MachineInstr &MI, MCInst &OutMI) const;
+ MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
+ const SuperHSubtarget &Subtarget) const;
+
+private:
+ MCContext &Ctx;
+ AsmPrinter &Printer;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPERH_MCINST_LOWER_H
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 32bdf20b8dd95..a8781f921dcac 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -12,9 +12,13 @@
//===----------------------------------------------------------------------===//
#include "SuperHRegisterInfo.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "SuperHTargetMachine.h"
#include "SuperHFrameLowering.h"
#include "SuperHSubtarget.h"
#include "SuperH.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
@@ -30,13 +34,31 @@ SuperHRegisterInfo::SuperHRegisterInfo(const SuperHSubtarget &ST)
: SuperHGenRegisterInfo(SH::R0, /*DwarfFlavour*/0, /*EHFlavor*/0,
/*PC*/SH::PC), Subtarget(ST) {}
+const TargetRegisterClass *SuperHRegisterInfo::getPointerRegClass(unsigned Kind) const {
+ return &SH::GPRRegClass;
+}
+
const TargetRegisterClass *SuperHRegisterInfo::intRegClass(unsigned Size) const {
return &SH::GPRRegClass;
}
+const MCPhysReg *SuperHRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
+ return CSR_SH_SaveList;
+}
+
+const uint32_t *SuperHRegisterInfo::getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const {
+ return CSR_SH_RegMask;
+}
+
BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
+ // R0 and R1 are always reserved as return slots.
+ Reserved.set(SH::R0);
+ Reserved.set(SH::R1);
+
+ // Also reserve the stack frame.
+ Reserved.set(SH::R14);
return Reserved;
}
@@ -44,35 +66,33 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS) const {
- llvm_unreachable("Unsupported eliminateFrameIndex");
- return true;
-}
-
-bool
-SuperHRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
- return true;
-}
-
-bool
-SuperHRegisterInfo::requiresFrameIndexScavenging(
- const MachineFunction &MF) const {
- return true;
-}
-
-bool
-SuperHRegisterInfo::requiresFrameIndexReplacementScavenging(
- const MachineFunction &MF) const {
- return true;
-}
-
-bool
-SuperHRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
- return true;
+ MachineInstr &MI = *II;
+ DebugLoc dl = MI.getDebugLoc();
+ MachineBasicBlock &MBB = *MI.getParent();
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+ const TargetInstrInfo &TII = *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
+ int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
+
+ // NOTE: Stack grows down, so flip this.
+ int Offset = -MFI.getObjectOffset(FrameIndex);
+
+ if (MI.getOpcode() == SH::SHFrmIdx) {
+
+ // TODO: Lower frames that can't be expressed in 4 bits.
+
+ Register DstReg = MI.getOperand(0).getReg();
+ MachineInstr *New = BuildMI(MBB, MI, dl, TII.get(SH::MOVLD4RmiRn), DstReg)
+ .addReg(SH::R14)
+ .addImm(Offset / 4);
+
+ MI.eraseFromParent();
+ return false;
+ }
+ return false;
}
Register SuperHRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
- llvm_unreachable("Unsupported getFrameRegister");
-}
-const MCPhysReg *SuperHRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
- return nullptr;
+ return SH::R14;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index ed3200f7b0101..c5c6dbb88e2af 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -30,21 +30,14 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
SuperHRegisterInfo(const SuperHSubtarget &Subtarget);
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
+ const uint32_t *getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const override;
+ const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const override;
BitVector getReservedRegs(const MachineFunction &MF) const override;
-
- bool requiresRegisterScavenging(const MachineFunction &MF) const override;
- bool requiresFrameIndexScavenging(const MachineFunction &MF) const override;
- bool requiresFrameIndexReplacementScavenging(
- const MachineFunction &MF) const override;
-
- bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override;
-
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;
Register getFrameRegister(const MachineFunction &MF) const override;
-
const TargetRegisterClass *intRegClass(unsigned Size) const;
};
diff --git a/llvm/lib/Target/SuperH/SuperHSelectionDAGInfo.cpp b/llvm/lib/Target/SuperH/SuperHSelectionDAGInfo.cpp
new file mode 100644
index 0000000000000..69cbbff4374b0
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHSelectionDAGInfo.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHSelectionDAGInfo.h"
+
+#define GET_SDNODE_DESC
+#include "SuperHGenSDNodeInfo.inc"
+
+using namespace llvm;
+
+SuperHSelectionDAGInfo::SuperHSelectionDAGInfo()
+ : SelectionDAGGenTargetInfo(SuperHGenSDNodeInfo) {}
+
+SuperHSelectionDAGInfo::~SuperHSelectionDAGInfo() = default;
diff --git a/llvm/lib/Target/SuperH/SuperHSelectionDAGInfo.h b/llvm/lib/Target/SuperH/SuperHSelectionDAGInfo.h
new file mode 100644
index 0000000000000..8eacbd0fbceaf
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHSelectionDAGInfo.h
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHSELECTIONDAGINFO_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHSELECTIONDAGINFO_H
+
+#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
+
+#define GET_SDNODE_ENUM
+#include "SuperHGenSDNodeInfo.inc"
+
+namespace llvm {
+
+class SuperHSelectionDAGInfo : public SelectionDAGGenTargetInfo {
+public:
+ SuperHSelectionDAGInfo();
+
+ ~SuperHSelectionDAGInfo() override;
+};
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SUPERH_SUPERHSELECTIONDAGINFO_H
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
index 1f831a528a15a..1cff7f9f647b4 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
@@ -12,6 +12,9 @@
#include "SuperHSubtarget.h"
#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h"
using namespace llvm;
@@ -19,4 +22,28 @@ using namespace llvm;
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
-#include "SuperHGenSubtargetInfo.inc"
\ No newline at end of file
+#include "SuperHGenSubtargetInfo.inc"
+
+SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
+ const StringRef &FS, const TargetMachine &TM)
+ : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, TuneCPU, FS),
+ InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
+ TLInfo(TM, *this), FrameLowering(*this) {
+ // TSInfo = std::make_unique<SuperHSelectionDAGInfo>();
+}
+
+SuperHSubtarget::~SuperHSubtarget() = default;
+
+
+SuperHSubtarget &SuperHSubtarget::initializeSubtargetDependencies(
+ StringRef CPU, StringRef TuneCPU, StringRef FS) {
+ const Triple &TT = getTargetTriple();
+ // Determine default and user specified characteristics
+ std::string CPUName = std::string(CPU);
+ if (TuneCPU.empty())
+ TuneCPU = CPUName;
+
+ // Parse features string.
+ ParseSubtargetFeatures(CPUName, TuneCPU, FS);
+ return *this;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.h b/llvm/lib/Target/SuperH/SuperHSubtarget.h
index b5c38b7cb7ba4..7a2149e384b51 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.h
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.h
@@ -13,11 +13,22 @@
#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHSUBTARGET_H
#define LLVM_LIB_TARGET_SUPERH_SUPERHSUBTARGET_H
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "SuperHFrameLowering.h"
+#include "SuperHISelLowering.h"
+#include "SuperHInstrInfo.h"
+#include "SuperHSelectionDAGInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TargetParser/Triple.h"
+
#define GET_SUBTARGETINFO_HEADER
#include "SuperHGenSubtargetInfo.inc"
-
namespace llvm {
+class StringRef;
+
class SuperHSubtarget : public SuperHGenSubtargetInfo {
enum SuperHArchEnum {
SHDefault,
@@ -26,22 +37,48 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
SH3, SH3E,
SH4, SH4A
};
-
+
SuperHArchEnum SHArchVersion;
+ SuperHInstrInfo InstrInfo;
+ SuperHTargetLowering TLInfo;
+ SuperHSelectionDAGInfo TSInfo;
+ SuperHFrameLowering FrameLowering;
+
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
bool ATTRIBUTE = DEFAULT;
#include "SuperHGenSubtargetInfo.inc"
+public:
+ SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
+ const StringRef &FS, const TargetMachine &TM);
+
+ ~SuperHSubtarget() override;
+
+ const SuperHInstrInfo *getInstrInfo() const override { return &InstrInfo; }
+ const TargetFrameLowering *getFrameLowering() const override {
+ return &FrameLowering;
+ }
+ const SuperHRegisterInfo *getRegisterInfo() const override {
+ return &InstrInfo.getRegisterInfo();
+ }
+ const SuperHSelectionDAGInfo *getSelectionDAGInfo() const override {
+ return &TSInfo;
+ }
+ const SuperHTargetLowering *getTargetLowering() const override {
+ return &TLInfo;
+ }
+
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
bool GETTER() const { return ATTRIBUTE; }
#include "SuperHGenSubtargetInfo.inc"
-public:
-
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
+ SuperHSubtarget &initializeSubtargetDependencies(StringRef CPU,
+ StringRef TuneCPU,
+ StringRef FS);
};
} // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 7001640d4dc15..27a5bf798a5a5 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -11,8 +11,11 @@
//===----------------------------------------------------------------------===//
#include "SuperHTargetMachine.h"
+#include "SuperH.h"
+#include "SuperHSubtarget.h"
#include "TargetInfo/SuperHTargetInfo.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Compiler.h"
@@ -25,6 +28,33 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSuperHTarget() {
RegisterTargetMachine<SuperHTargetMachine> SHLE(getTheSuperHLETarget());
}
+//
+// PASS CONFIG
+//
+
+namespace {
+class SuperHPassConfig : public TargetPassConfig {
+public:
+ SuperHPassConfig(SuperHTargetMachine &TM, PassManagerBase &PM)
+ : TargetPassConfig(TM, PM) {}
+
+ bool addInstSelector() override;
+ SuperHTargetMachine &getSuperHTargetMachine() const {
+ return getTM<SuperHTargetMachine>();
+ }
+};
+
+bool SuperHPassConfig::addInstSelector() {
+ addPass(createSuperHISelDag(getSuperHTargetMachine(), getOptLevel()));
+ return false;
+}
+} // namespace
+
+
+//
+// TARGET MACHINE
+//
+
SuperHTargetMachine::~SuperHTargetMachine() {}
/// Create a SuperH architecture model.
@@ -37,7 +67,31 @@ SuperHTargetMachine::SuperHTargetMachine(const Target &T, const Triple &TT,
: CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,
RM.value_or(Reloc::Static),
getEffectiveCodeModel(CM, CodeModel::Small),
- OL) {
+ OL), TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
initAsmInfo();
+}
+
+TargetPassConfig *SuperHTargetMachine::createPassConfig(PassManagerBase &PM) {
+ return new SuperHPassConfig(*this, PM);
+}
+
+const TargetSubtargetInfo *
+SuperHTargetMachine::getSubtargetImpl(const Function &F) const {
+ Attribute CPUAttr = F.getFnAttribute("target-cpu");
+ Attribute TuneAttr = F.getFnAttribute("tune-cpu");
+ Attribute FSAttr = F.getFnAttribute("target-features");
+
+ std::string CPU =
+ CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
+ std::string TuneCPU =
+ TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
+ std::string FS =
+ FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
+
+ resetTargetOptions(F);
+ if (!ST) {
+ ST = std::make_unique<SuperHSubtarget>(CPU, TuneCPU, FS, *this);
+ }
+ return ST.get();
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.h b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
index 2b090d24ac13f..3b2872ed50ffd 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.h
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
@@ -13,13 +13,18 @@
#ifndef LLVM_LIB_TARGET_SPARC_SPARCTARGETMACHINE_H
#define LLVM_LIB_TARGET_SPARC_SPARCTARGETMACHINE_H
+#include "SuperHSubtarget.h"
#include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/Target/TargetMachine.h"
#include <optional>
namespace llvm {
class SuperHTargetMachine : public CodeGenTargetMachineImpl {
+ std::unique_ptr<TargetLoweringObjectFile> TLOF;
+ mutable std::unique_ptr<SuperHSubtarget> ST;
+
public:
SuperHTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
@@ -28,6 +33,12 @@ class SuperHTargetMachine : public CodeGenTargetMachineImpl {
bool JIT);
~SuperHTargetMachine() override;
+ const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override;
+ TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
+ TargetLoweringObjectFile *getObjFileLowering() const override {
+ return TLOF.get();
+ }
+
};
} // end namespace llvm
diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp
index d0a5ae9544b7e..1c87d82305e7b 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -563,8 +563,15 @@ static std::string computeSuperHDataLayout(const Triple &T) {
// 32-bit pointers, 32 bit aligned
Ret += "-p:32:32";
- // 32 bit integers, 32 bit aligned
+ // Integer alignments
+ Ret += "-i18:32";
+ Ret += "-i16:32";
Ret += "-i32:32";
+ Ret += "-i64:64";
+
+ // Floating alignments
+ Ret += "-f32:32";
+ Ret += "-f64:64";
// 32 bit alignment of objects of aggregate type
Ret += "-a:0:32";
>From 7bf5134020d2b1d875f7be846ed5e57a188e460c Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 9 Aug 2026 05:20:38 +0200
Subject: [PATCH 16/39] Add more instructions, expand sdiv and udiv
---
.../SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 3 +-
llvm/lib/Target/SuperH/SuperH.td | 39 +-
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 25 +-
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 16 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 65 ++
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 5 +
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 559 +++++++++++++++---
7 files changed, 604 insertions(+), 108 deletions(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 95d0618ad6478..3ddbb766796f1 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -50,8 +50,7 @@ void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostrea
// Print immediates
if (Op.isImm()) {
- assert(Op.getImm() <= 255 && "Only 8-bit immediates are supported.");
- O << "#" << Op.getImm();
+ O << Op.getImm();
return;
}
}
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index fad2c4fb6f106..03809c4d7a31d 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -23,14 +23,17 @@ include "llvm/TableGen/SearchableTable.td"
// NOTE: Some SH4 CPUs support FSCA and FSRRA despite their
// ISA manuals not specifying so.
+def FeatureFPU : SubtargetFeature<"fp32", "HasFPU", "true",
+ "Enable use of 32-bit floating point instructions.">;
+def FeatureFPU64 : SubtargetFeature<"fp64", "HasFP64", "true",
+ "Enable use of 64-bit floating point instructions.",
+ [FeatureFPU]>;
def FeatureFSCA : SubtargetFeature<"fsca", "HasFSCA", "true",
- "Enable use of fsca instruction.">;
+ "Enable use of fsca instruction.",
+ [FeatureFPU]>;
def FeatureFSRRA : SubtargetFeature<"fsrra", "HasFSRRA", "true",
- "Enable use of fsrra instruction.">;
-def FeatureFP32 : SubtargetFeature<"fp32", "HasFP32", "true",
- "Enable use of 32-bit floating point instructions.">;
-def FeatureFP64 : SubtargetFeature<"fp64", "HasFP64", "true",
- "Enable use of 64-bit floating point instructions.">;
+ "Enable use of fsrra instruction.",
+ [FeatureFPU]>;
def FeatureDSP : SubtargetFeature<"dsp", "HasDSP", "true",
"Enable SuperH DSP Extensions">;
@@ -38,31 +41,29 @@ def FeatureDSP : SubtargetFeature<"dsp", "HasDSP", "true",
// SuperH CPU Family features
//===----------------------------------------------------------------------===//
-def FeatureSH1 : SubtargetFeature<"sh1", "SHArchVersion", "SH1",
- "SH-1 ISA Support">;
def FeatureSH2 : SubtargetFeature<"sh2", "SHArchVersion", "SH2",
"SH-2 ISA Support",
- [FeatureSH1]>;
+ []>;
def FeatureSH2E : SubtargetFeature<"sh2e", "SHArchVersion", "SH2E",
"SH-2E ISA Support",
- [FeatureSH1, FeatureSH2, FeatureFP32]>;
+ [FeatureSH2, FeatureFPU]>;
def FeatureSH2A : SubtargetFeature<"sh2a", "SHArchVersion", "SH2A",
"SH-2A ISA Support",
- [FeatureSH1, FeatureSH2, FeatureFP32, FeatureFP64]>;
+ [FeatureSH2, FeatureFPU, FeatureFPU64]>;
def FeatureSH3 : SubtargetFeature<"sh3", "SHArchVersion", "SH3",
"SH-3 ISA Support",
- [FeatureSH1, FeatureSH2]>;
+ [FeatureSH2]>;
def FeatureSH3E : SubtargetFeature<"sh3e", "SHArchVersion", "SH3E",
"SH-3E ISA Support",
- [FeatureSH1, FeatureSH2, FeatureFP32]>;
+ [FeatureSH2, FeatureFPU]>;
def FeatureSH4 : SubtargetFeature<"sh4", "SHArchVersion", "SH4",
"SH-4 ISA Support",
- [FeatureSH1, FeatureSH2, FeatureSH3, FeatureFP32,
- FeatureFP64]>;
+ [FeatureSH2, FeatureSH3, FeatureFPU,
+ FeatureFPU64]>;
def FeatureSH4A : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
"SH-4A ISA Support",
- [FeatureSH1, FeatureSH2, FeatureSH3, FeatureSH4,
- FeatureFP32, FeatureFP64, FeatureFSCA, FeatureFSRRA]>;
+ [FeatureSH2, FeatureSH3, FeatureSH4,
+ FeatureFPU, FeatureFPU64, FeatureFSCA, FeatureFSRRA]>;
//===----------------------------------------------------------------------===//
// SuperH Processors
@@ -73,8 +74,8 @@ include "SuperHSchedule.td"
class ProcModel<string Name, list<SubtargetFeature> Features>
: ProcessorModel<Name, GenericSuperHModel, Features>;
-def : ProcModel<"generic", [FeatureSH4]>;
-def : ProcModel<"sh1", [FeatureSH1]>;
+def : ProcModel<"generic", [FeatureSH2]>;
+def : ProcModel<"sh1", []>;
def : ProcModel<"sh2", [FeatureSH2]>;
def : ProcModel<"sh2e", [FeatureSH2E]>;
def : ProcModel<"sh2a", [FeatureSH2A]>;
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 645e2884e269f..d14e187479bb3 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -19,6 +19,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/DebugLog.h"
#define DEBUG_TYPE "sh-isel"
#define PASS_NAME "SH DAG->DAG Instruction Selection"
@@ -39,15 +40,19 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
InlineAsm::ConstraintCode ConstraintCode,
std::vector<SDValue> &OutOps) override;
- bool trySelectRET(SDNode *N);
- bool trySelectFrameIndex(SDNode *N);
+ bool SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValue Rhs);
// Include the pieces autogenerated from the target description.
#include "SuperHGenDAGISel.inc"
private:
void Select(SDNode *N) override;
+
bool trySelect(SDNode *N);
+ bool trySelectRET(SDNode *N);
+ bool trySelectSDIV(SDNode *N);
+ bool trySelectUDIV(SDNode *N);
+ bool trySelectFrameIndex(SDNode *N);
const SuperHSubtarget *Subtarget;
};
@@ -75,6 +80,22 @@ bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
return false;
}
+
+//===----------------------------------------------------------------------===//
+// Address Lowering
+//===----------------------------------------------------------------------===//
+
+bool SuperHDAGToDAGISel::SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValue Rhs) {
+ return false;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Branch Lowering
+//===----------------------------------------------------------------------===//
+
// Due to delay slots there needs to be a bit more smarts
// in here.
bool SuperHDAGToDAGISel::trySelectRET(SDNode *N) {
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index 442a543807aa3..df62cf6e9cfc4 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -152,7 +152,7 @@ class InstRm<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patter
// Immediate -> Register Instruction
// <opop|rnrn|iiiiiiii>
//===----------------------------------------------------------------------===//
-class InstI8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+class InstRnI8<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
: SHInst16<outs, ins, asmstr, pattern> {
// Opcode
@@ -170,7 +170,7 @@ class InstI8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
// (disp:8) -> Register Instruction
// <opop|rnrn|dddddddd>
//===----------------------------------------------------------------------===//
-class InstD8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+class InstRnD8<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
: SHInst16<outs, ins, asmstr, pattern> {
@@ -189,7 +189,7 @@ class InstD8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
// (Register + disp:4) -> Register Instruction
// <opop|rnrn|rmrm|dddd>
//===----------------------------------------------------------------------===//
-class InstRmD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+class InstRmRnD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
: SHInst16<outs, ins, asmstr, pattern> {
// Opcode
@@ -209,7 +209,7 @@ class InstRmD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pa
// (disp:4) -> Register Instruction
// <opopopop|rnrn|dddd>
//===----------------------------------------------------------------------===//
-class InstD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+class InstRnD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
: SHInst16<outs, ins, asmstr, pattern> {
// Opcode
@@ -227,7 +227,7 @@ class InstD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
// (disp:4 + Register) -> Reserved Register Instruction
// <opopopop|rmrm|dddd>
//===----------------------------------------------------------------------===//
-class InstD4RmRr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+class InstRmD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
: SHInst16<outs, ins, asmstr, pattern> {
// Opcode
@@ -245,7 +245,7 @@ class InstD4RmRr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> p
// (disp:8) Instruction
// <opopopop|dddddddd>
//===----------------------------------------------------------------------===//
-class InstD8Rr<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+class InstD8<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
: SHInst16<outs, ins, asmstr, pattern> {
// Opcode
@@ -261,7 +261,7 @@ class InstD8Rr<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
// (imm:8) Instruction
// <opopopop|iiiiiiii>
//===----------------------------------------------------------------------===//
-class InstI8Rr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+class InstI8<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
: SHInst16<outs, ins, asmstr, pattern> {
// Opcode
@@ -277,7 +277,7 @@ class InstI8Rr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pat
// (disp:12) Instruction
// <opop|dddddddddddd>
//===----------------------------------------------------------------------===//
-class InstD12Rr<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
+class InstD12<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []>
: SHInst16<outs, ins, asmstr, pattern> {
// Opcode
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 303048a47389a..9b76cd1d4a9b6 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -17,6 +17,8 @@
#include "SuperHTargetMachine.h"
#include "SuperH.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/MC/TargetRegistry.h"
@@ -48,4 +50,67 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
// Otherwise this is not possible.
llvm_unreachable("Impossible reg-to-reg copy");
+}
+
+bool SuperHInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
+ unsigned OpCode = MI.getOpcode();
+ switch(OpCode) {
+ case SH::DIVURmRn:
+ case SH::DIVSRmRn:
+ return expandDIV(OpCode, MI);
+ default:
+ return false;
+ }
+}
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Pseudo Instruction Expansion
+//===----------------------------------------------------------------------===//
+
+// Expands the division psuedo instructions into valid SuperH sequences.
+// SuperH sets the division mode with an struction inserted before.
+bool SuperHInstrInfo::expandDIV(unsigned Opcode, MachineInstr &MI) const {
+ assert(MI.getOperand(0).isReg() && "Expected register in op0 for expansion!");
+ assert(MI.getOperand(1).isReg() && "Expected register in op1 for expansion!");
+ auto &MBB = *MI.getParent();
+ auto Lhs = MI.getOperand(0).getReg();
+ auto Rhs = MI.getOperand(1).getReg();
+ auto DL = MI.getDebugLoc();
+
+ switch(Opcode) {
+
+ // Expand DIVURmRn to the following sequence:
+ // div0u
+ // div1 Rm, Rn
+ case SH::DIVURmRn: {
+ BuildMI(MBB, MI, DL, get(SH::DIV0U));
+ BuildMI(MBB, MI, DL, get(SH::DIV1RmRn), Rhs)
+ .addReg(Lhs);
+ MI.removeFromParent();
+ return true;
+ }
+
+ // Expand DIVSRmRn to the following sequence:
+ // div0s Rm, Rn
+ // div1 Rm, Rn
+ case SH::DIVSRmRn: {
+ BuildMI(MBB, MI, DL, get(SH::DIV0SRmRn))
+ .addReg(Rhs)
+ .addReg(Lhs);
+ BuildMI(MBB, MI, DL, get(SH::DIV1RmRn), Rhs)
+ .addReg(Lhs);
+ MI.removeFromParent();
+ return true;
+ }
+
+ // This shouldn't be reached.
+ default: {
+ llvm_unreachable("expandDIV was wrongfully called on a non-div pseudo!");
+ return false;
+ }
+ }
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 65231455267a9..ae47b75d7ffc0 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -40,6 +40,11 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
Register DestReg, Register SrcReg, bool KillSrc,
bool RenamableDest = false,
bool RenamableSrc = false) const override;
+
+ bool expandPostRAPseudo(MachineInstr &MI) const override;
+
+private:
+ bool expandDIV(unsigned Opcode, MachineInstr &MI) const;
};
const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 8bd12bd5cfcbb..4a8414f16f11a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -4,29 +4,33 @@
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
///
/// \file
/// This file describes the SuperH instruction set, defining the instructions
/// and properties of the instructions which are needed for code generation,
/// machine code emission, and analysis.
///
+/// The instructions in this file in particular cover SH1-2.
+/// later version and extensions are in their respective files.
+///
/// The subsystems are ordered after the instruction classification that
/// The SuperH ISA manuals use.
///
/// See: https://www.shared-ptr.com/sh_insns.html
+/// See: https://saturnopensdk.github.io/
///
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Instruction Formats
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
include "SuperHInstrFormats.td"
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Instruction Patterns
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
defvar SH = DefaultMode;
def sh_ptr_rc : RegClassByHwMode<[SH], [GPR]>;
@@ -37,18 +41,17 @@ def ptr_op : RegisterOperand<sh_ptr_rc> {
let DecoderMethod = "DecodeIntRegsRegisterClass";
}
-
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// SuperH Type Profiles
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
def SHSDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
def SHSDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
def SHSDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// SuperH Specific Nodes
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
def SHCallSeqStart : SDNode<"ISD::CALLSEQ_START", SHSDT_CallSeqStart,
[SDNPHasChain, SDNPOutGlue]>;
@@ -64,9 +67,9 @@ def SHRet : SDNode<"SHISD::RET", SDTNone,
[SDNPHasChain, SDNPOptInGlue,
SDNPVariadic]>;
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Operand Classes
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Base Operand Class
class SHOpClass<string name,
@@ -94,9 +97,9 @@ def SHMemClass : SHOpClass<"Mem"> {
let RenderMethod = "addMemOperands";
}
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Operands
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Immediate
class SHImmOp<int width, ValueType vt>
@@ -165,22 +168,51 @@ def MemR0I : Operand<iPTR> {
let WantsRoot = true in
def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
+//===--------------------------------------------------------------------------===//
+// Predicates
+//===--------------------------------------------------------------------------===//
+
+def HasFSCA : Predicate<"Subtarget->hasFSCA()">,
+ AssemblerPredicate<(all_of FeatureFSCA)>;
+
+def HasFSRRA : Predicate<"Subtarget->hasFSRRA()">,
+ AssemblerPredicate<(all_of FeatureFSRRA)>;
+
+def HasFPU : Predicate<"Subtarget->hasFPU()">,
+ AssemblerPredicate<(all_of FeatureFPU)>;
+
+def HasDSP : Predicate<"Subtarget->hasDSP()">,
+ AssemblerPredicate<(all_of FeatureDSP)>;
+def HasSH2 : Predicate<"Subtarget->hasSH2Inst()">,
+ AssemblerPredicate<(all_of FeatureSH2)>;
+def HasSH2E : Predicate<"Subtarget->hasSH2EInst()">,
+ AssemblerPredicate<(all_of FeatureSH2E)>;
+def HasSH2A : Predicate<"Subtarget->hasSH2AInst()">,
+ AssemblerPredicate<(all_of FeatureSH2A)>;
-//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-// Instruction Definitions
-//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
+def HasSH3 : Predicate<"Subtarget->hasSH3Inst()">,
+ AssemblerPredicate<(all_of FeatureSH3)>;
+def HasSH3E : Predicate<"Subtarget->hasSH3EInst()">,
+ AssemblerPredicate<(all_of FeatureSH3E)>;
+def HasSH4 : Predicate<"Subtarget->hasSH4Inst()">,
+ AssemblerPredicate<(all_of FeatureSH4)>;
+def HasSH4A : Predicate<"Subtarget->hasSH4AInst()">,
+ AssemblerPredicate<(all_of FeatureSH4A)>;
-//===----------------------------------------------------------------------===//
-// Data Transfer Instructions
-//===----------------------------------------------------------------------===//
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Data Transfer Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// mov Rm, Rn
let hasSideEffects = 0 in
@@ -191,77 +223,286 @@ def MOVRmRn : InstRmRn<0b0110000000000011,
// mov #imm:8, Rn
let hasSideEffects = 0 in
-def MOVI8Rn : InstI8Rn<0b1110000000000000,
+def MOVI8Rn : InstRnI8<0b1110000000000000,
(outs GPR:$Rn), (ins imm8:$imm),
"mov #$imm,$Rn",
[(set i32:$Rn, imm8:$imm)]>;
+// mov @(disp, PC), R0
+let hasSideEffects = 0, mayLoad = 1, Defs = [R0] in
+def MOVAD8PCR0 : InstD8<0b1100011100000000,
+ (outs), (ins disp8:$disp),
+ "mov @($disp,PC),R0",
+ []>;
+
+// mov.w @(disp,PC), Rn
+let hasSideEffects = 0, mayLoad = 1 in
+def MOVWD8PCRn : InstRnD8<0b1001000000000000,
+ (outs GPR:$Rn), (ins disp8:$disp),
+ "mov.w @($disp,PC),$Rn",
+ [(set i32:$Rn, (sextloadi16 addr:$disp))]>;
+
+// mov.l @(disp,PC), Rn
+let hasSideEffects = 0, mayLoad = 1 in
+def MOVLD8PCRn : InstRnD8<0b1101000000000000,
+ (outs GPR:$Rn), (ins disp8:$disp),
+ "mov.l @($disp,PC),$Rn",
+ [(set i32:$Rn, (load addr:$disp))]>;
+
+// movt Rn
+def MOVTRn : InstRn<0b0000000000101001,
+ (outs GPR:$Rn), (ins),
+ "movt $Rn",
+ []>;
-// mova @(disp,PC), R0
+// swap.b Rm,Rn
+def SWAPBRmRn : InstRmRn<0b0110000000001000,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "swap.b $Rm,$Rn",
+ []>;
+// swap.w Rm,Rn
+def SWAPWRmRn : InstRmRn<0b0110000000001001,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "swap.w $Rm,$Rn",
+ []>;
-//===----------------------------------------------------------------------===//
+// xtrct Rm,Rn
+def XTRCTRmRn : InstRmRn<0b0010000000001101,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "xtrct $Rm,$Rn",
+ []>;
+
+//===--------------------------------------------------------------------------===//
// Load Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Indirect Memory -> Register Load
let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
- def MOVBRmiRn : InstRmRn<0b0110000000000000,
+
+ // mov.b @Rm, Rn
+ def MOVBRmiRn : InstRmRn<0b0110000000000000,
(outs GPR:$Rn), (ins GPR:$Rm),
"mov.b @$Rm,$Rn",
[(set i32:$Rn, (sextloadi8 i32:$Rm))]>;
- def MOVWRmiRn : InstRmRn<0b0110000000000001,
+ // mov.w @Rm, Rn
+ def MOVWRmiRn : InstRmRn<0b0110000000000001,
(outs GPR:$Rn), (ins GPR:$Rm),
"mov.w @$Rm,$Rn",
[(set i32:$Rn, (sextloadi16 i32:$Rm))]>;
- def MOVLRmiRn : InstRmRn<0b0110000000000010,
+ // mov.l @Rm, Rn
+ def MOVLRmiRn : InstRmRn<0b0110000000000010,
(outs GPR:$Rn), (ins GPR:$Rm),
"mov.l @$Rm,$Rn",
[(set i32:$Rn, (load i32:$Rm))]>;
-}
-
-// Indirect Memory w/ Displacement -> Register Load
-let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
- def MOVLD4RmiRn : InstRmD4Rn<0b0101000000000000,
+
+ // mov.b @Rm+, Rn
+ def MOVBRminciRn : InstRmRn<0b0110000000000100,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.b @$Rm+,$Rn",
+ []>;
+
+ // mov.w @Rm+, Rn
+ def MOVWRminciRn : InstRmRn<0b0110000000000101,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.w @$Rm+,$Rn",
+ []>;
+
+ // mov.l @Rm+, Rn
+ def MOVLRminciRn : InstRmRn<0b0110000000000110,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.l @$Rm+,$Rn",
+ []>;
+
+ // mov.b @(disp, Rm), R0
+ let Defs = [R0] in
+ def MOVBD4RmiR0 : InstRmD4<0b1000010000000000,
+ (outs), (ins GPR:$Rm, disp4:$disp),
+ "mov.b @($disp,$Rm),R0",
+ []>;
+
+ // mov.w @(disp, Rm), R0
+ let Defs = [R0] in
+ def MOVWD4RmiR0 : InstRmD4<0b1000010100000000,
+ (outs), (ins GPR:$Rm, disp4:$disp),
+ "mov.w @($disp,$Rm),R0",
+ []>;
+
+ // mov.l @(disp, Rm), Rn
+ def MOVLD4RmiRn : InstRmRnD4<0b0101000000000000,
(outs GPRMem:$Rn), (ins GPR:$Rm, disp4:$disp),
- "mov.l @($disp, $Rm),$Rn",
+ "mov.l @($disp,$Rm),$Rn",
+ []>;
+
+ // mov.b @(R0,Rm),Rn
+ let Uses = [R0] in
+ def MOVBR0RmiRn : InstRmRn<0b0000000000001100,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.b @(R0,Rm),Rn",
+ []>;
+
+ // mov.w @(R0,Rm),Rn
+ let Uses = [R0] in
+ def MOVWR0RmiRn : InstRmRn<0b0000000000001101,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.w @(R0,$Rm),$Rn",
+ []>;
+
+ // mov.l @(R0,Rm),Rn
+ let Uses = [R0] in
+ def MOVLR0RmiRn : InstRmRn<0b0000000000001110,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "mov.l @(R0,$Rm),$Rn",
[]>;
- // "mov.l", [(set i32:$Rn, (load addr:$disp))]>;
+ // mov.b @(disp,GBR),R0
+ let Defs = [R0], Uses = [GBR] in
+ def MOVBD12GBRiR0 : InstD8<0b1100010000000000,
+ (outs), (ins disp12:$disp),
+ "mov.b @($disp,GBR),R0",
+ []>;
+
+ // mov.w @(disp,GBR),R0
+ let Defs = [R0], Uses = [GBR] in
+ def MOVWD12GBRiR0 : InstD8<0b1100010100000000,
+ (outs), (ins disp12:$disp),
+ "mov.w @($disp,GBR),R0",
+ []>;
+
+ // mov.l @(disp,GBR),R0
+ let Defs = [R0], Uses = [GBR] in
+ def MOVLD12GBRiR0 : InstD8<0b1100011000000000,
+ (outs), (ins disp12:$disp),
+ "mov.l @($disp,GBR),R0",
+ []>;
}
-//===----------------------------------------------------------------------===//
+
+//===--------------------------------------------------------------------------===//
// Store Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Register -> Indirect Memory Store
let hasSideEffects = 0, mayStore = 1 in {
- def MOVBRmRni : InstRmRn<0b0010000000000000,
+
+ // mov.b Rm, @Rn
+ def MOVBRmRni : InstRmRn<0b0010000000000000,
(outs), (ins GPRMem:$Rn, GPR:$Rm),
"mov.b $Rm,@$Rn",
- [(truncstorei8 GPRMem:$Rn, i32:$Rm)]>;
+ [(truncstorei8 i32:$Rm, GPRMem:$Rn)]>;
- def MOVWRmRni : InstRmRn<0b0010000000000001,
- (outs), (ins GPRMem:$Rn, GPR:$Rm),
+ // mov.w Rm, @Rn
+ def MOVWRmRni : InstRmRn<0b0010000000000001,
+ (outs), (ins GPR:$Rm, GPRMem:$Rn),
"mov.w $Rm,@$Rn",
- [(truncstorei16 GPRMem:$Rn, i32:$Rm)]>;
+ [(truncstorei16 i32:$Rm, GPRMem:$Rn)]>;
- def MOVLRmRni : InstRmRn<0b0010000000000010,
+ // mov.l Rm, @Rn
+ def MOVLRmRni : InstRmRn<0b0010000000000010,
(outs), (ins GPRMem:$Rn, GPR:$Rm),
"mov.l $Rm,@$Rn",
- [(store GPRMem:$Rn, i32:$Rm)]>;
+ [(store i32:$Rm, GPRMem:$Rn)]>;
+
+ // mov.b Rm, @-Rn
+ def MOVBRmRndeci : InstRmRn<0b0010000000000100,
+ (outs), (ins GPRMem:$Rn, GPR:$Rm),
+ "mov.b $Rm, at -$Rn",
+ []>;
+
+ // mov.w Rm, @-Rn
+ def MOVWRmRndeci : InstRmRn<0b0010000000000101,
+ (outs), (ins GPR:$Rm, GPRMem:$Rn),
+ "mov.w $Rm, at -$Rn",
+ []>;
+
+ // mov.l Rm, @-Rn
+ def MOVLRmRndeci : InstRmRn<0b0010000000000110,
+ (outs), (ins GPRMem:$Rn, GPR:$Rm),
+ "mov.l $Rm, at -$Rn",
+ []>;
+
+ // mov.b R0, @(disp, Rn)
+ let Uses = [R0] in
+ def MOVBR0D4Rni : InstRnD4<0b1000000000000000,
+ (outs GPR:$Rn), (ins disp4:$disp),
+ "mov.b R0,@($disp,$Rn)",
+ []>;
+
+ // mov.w R0, @(disp, Rn)
+ let Uses = [R0] in
+ def MOVWR0D4Rni : InstRnD4<0b1000000100000000,
+ (outs GPR:$Rn), (ins disp4:$disp),
+ "mov.w R0,@($disp,$Rn)",
+ []>;
+
+ // mov.l Rm, @(disp, Rn)
+ def MOVLRmD4Rni : InstRmRnD4<0b0001000000000000,
+ (outs GPR:$Rn), (ins GPR:$Rm, disp4:$disp),
+ "mov.l $Rm,@($disp,$Rn)",
+ []>;
+
+ // mov.b Rm,@(R0,Rn)
+ let Uses = [R0] in
+ def MOVBRmR0Rni : InstRmRn<0b0000000000000100,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "mov.b $Rm,@(R0,$Rn)",
+ []>;
+
+ // mov.w Rm,@(R0,Rn)
+ let Uses = [R0] in
+ def MOVWRmR0Rni : InstRmRn<0b0000000000000101,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "mov.w $Rm,@(R0,$Rn)",
+ []>;
+
+ // mov.l Rm,@(R0,Rn)
+ let Uses = [R0] in
+ def MOVLRmR0Rni : InstRmRn<0b0000000000000110,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "mov.l $Rm,@(R0,$Rn)",
+ []>;
+
+ // mov.b R0,@(disp,GBR)
+ let Uses = [R0, GBR] in
+ def MOVBR0D12GBRi : InstD8<0b1100000000000000,
+ (outs), (ins disp12:$disp),
+ "mov.b R0,@($disp,GBR)",
+ []>;
+
+ // mov.w R0,@(disp,GBR)
+ let Uses = [R0, GBR] in
+ def MOVWR0D12GBRi : InstD8<0b1100000100000000,
+ (outs), (ins disp12:$disp),
+ "mov.w R0,@($disp,GBR)",
+ []>;
+
+ // mov.l R0,@(disp,GBR)
+ let Uses = [R0, GBR] in
+ def MOVLR0D12GBRi : InstD8<0b1100001000000000,
+ (outs), (ins disp12:$disp),
+ "mov.l R0,@($disp,GBR)",
+ []>;
}
-//===----------------------------------------------------------------------===//
-// Arithmetic Instructions
-//===----------------------------------------------------------------------===//
-//
-// ADDITION
-//
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Arithmetic Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+
+
+//===--------------------------------------------------------------------------===//
+// Addition
+//===--------------------------------------------------------------------------===//
+
let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// add Rm, Rn
@@ -271,7 +512,7 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
[(set i32:$Rn, (add i32:$src, i32:$Rm))]>;
// add imm:8, Rn
- def ADDI8Rn : InstI8Rn<0b0011000000001100,
+ def ADDI8Rn : InstRnI8<0b0011000000001100,
(outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
"add #$imm,$Rn",
[(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
@@ -292,9 +533,12 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
}
-//
-// SUBTRACTION
-//
+
+
+//===--------------------------------------------------------------------------===//
+// Subtraction
+//===--------------------------------------------------------------------------===//
+
let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// sub Rm, Rn
@@ -319,15 +563,12 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// dt Rn
let Defs = [SR] in
- def DTRmRn : InstRn<0b0011000000001000,
- (outs GPR:$Rn), (ins GPR:$src),
- "dt $Rn",
- [(set i32:$Rn, (sub i32:$src, -1))]>;
+ def DTRn : InstRn<0b0100000000010000,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "dt $Rn",
+ [(set i32:$Rn, (sub i32:$src, -1))]>;
}
-//
-// NEGATION
-//
let hasSideEffects = 0 in {
// neg Rm, Rn
@@ -345,9 +586,12 @@ let hasSideEffects = 0 in {
}
-//
-// MULTIPLY
-//
+
+
+//===--------------------------------------------------------------------------===//
+// Multiplication
+//===--------------------------------------------------------------------------===//
+
let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// mul.l Rm, Rn
@@ -366,9 +610,156 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
}
-//===----------------------------------------------------------------------===//
-// Branch Instructions
-//===----------------------------------------------------------------------===//
+
+
+
+//===--------------------------------------------------------------------------===//
+// Division
+//===--------------------------------------------------------------------------===//
+
+let hasSideEffects = 0, isCommutable = 1 in {
+
+ // div0s Rm, Rn
+ let Defs = [SR] in
+ def DIV0SRmRn : InstRmRn<0b0010000000000111,
+ (outs), (ins GPR:$Rn, GPR:$Rm),
+ "div0s $Rm,$Rn",
+ []>;
+
+ // div0u
+ let Defs = [SR] in
+ def DIV0U : Inst<0b0000000000011001,
+ (outs), (ins),
+ "div0u",
+ []>;
+
+ // div1 Rm, Rn
+ let Defs = [SR] in
+ def DIV1RmRn : InstRmRn<0b0011000000000100,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "div1 $Rm,$Rn",
+ []>;
+}
+
+let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+
+ // Expand LLVM sdiv to the following sequence:
+ // div0s
+ // div1 Rm, Rn
+ def DIVSRmRn : SHPseudo<(outs GPR:$Rn),
+ (ins GPR:$Rm, GPR:$src),
+ "; divs $Rm, $Rn",
+ [(set i32:$Rn, (sdiv i32:$Rm, i32:$src))]>;
+
+ // Expand LLVM udiv to the following sequence:
+ // div0u
+ // div1 Rm, Rn
+ def DIVURmRn : SHPseudo<(outs GPR:$Rn),
+ (ins GPR:$Rm, GPR:$src),
+ "; divu $Rm, $Rn",
+ [(set i32:$Rn, (udiv i32:$Rm, i32:$src))]>;
+}
+
+
+
+
+//===--------------------------------------------------------------------------===//
+// Comparison
+//===--------------------------------------------------------------------------===//
+
+// cmp/eq #imm,R0
+let Defs = [R0, SR] in
+def CMPEQI8R0 : InstI8<0b1000100000000000,
+ (outs), (ins imm8:$imm),
+ "cmp/eq #imm,R0",
+ []>;
+
+// cmp/eq Rm,Rn
+let Defs = [SR] in
+def CMPEQRmRn : InstRmRn<0b0011000000000000,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "cmp/eq $Rm,$Rn",
+ []>;
+
+// cmp/hs Rm,Rn
+let Defs = [SR] in
+def CMPHSRmRn : InstRmRn<0b0011000000000010,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "cmp/hs $Rm,$Rn",
+ []>;
+
+// cmp/ge Rm,Rn
+let Defs = [SR] in
+def CMPGERmRn : InstRmRn<0b0011000000000011,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "cmp/ge $Rm,$Rn",
+ []>;
+
+// cmp/hi Rm,Rn
+let Defs = [SR] in
+def CMPHIRmRn : InstRmRn<0b0011000000000110,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "cmp/hi $Rm,$Rn",
+ []>;
+
+// cmp/gt Rm,Rn
+let Defs = [SR] in
+def CMPGTRmRn : InstRmRn<0b0011000000000111,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "cmp/gt $Rm,$Rn",
+ []>;
+
+// cmp/pl Rn
+let Defs = [SR] in
+def CMPPLRn : InstRn<0b0100000000010101,
+ (outs), (ins GPR:$Rn),
+ "cmp/pl $Rn",
+ []>;
+
+// cmp/pz Rn
+let Defs = [SR] in
+def CMPPZRn : InstRn<0b0100000000010001,
+ (outs), (ins GPR:$Rn),
+ "cmp/pz $Rn",
+ []>;
+
+// cmp/str Rm,Rn
+let Defs = [SR] in
+def CMPSTRRmRn : InstRmRn<0b0010000000001100,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "cmp/str $Rm,$Rn",
+ []>;
+
+
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Logic Operation Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Shift Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Branch Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// TODO: Port these to the updated way.
// def BF_Disp : BrOp_Disp8<0b1000101100000000, "bf">;
@@ -382,9 +773,9 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// def JMP_Rmi : BrOp_Rmi<0b0100000000101011, "jmp">;
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Call Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
let isCall = 1 in {
let Uses = [GBR] in
@@ -395,9 +786,9 @@ let isCall = 1 in {
}
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Return Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
def RTS : Inst<0b0000000000001011,
@@ -410,10 +801,19 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// System Control Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
+
+
+
+
+//===--------------------------------------------------------------------------===//
// Control Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// nop
let hasSideEffects = 1 in
@@ -424,11 +824,16 @@ let hasSideEffects = 1 in
def SLEEP : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
+//===--------------------------------------------------------------------------===//
+// Bigger Extensions
+//===--------------------------------------------------------------------------===//
+
+include "SuperHInstrDSP.td"
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Pseudo instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
// Helper instruction for mapping frame indices to relative frame pointer
// offsets.
>From 6879b5869b9ac347eac0fa5dcba26a6d699cb2ad Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 10 Aug 2026 09:48:31 +0200
Subject: [PATCH 17/39] Add rt stubs for div, delay slots and more instrs
---
compiler-rt/lib/builtins/superh/divhi3.S | 24 +
compiler-rt/lib/builtins/superh/divqi3.S | 24 +
compiler-rt/lib/builtins/superh/divsi3.S | 24 +
compiler-rt/lib/builtins/superh/udivhi3.S | 24 +
compiler-rt/lib/builtins/superh/udivqi3.S | 24 +
compiler-rt/lib/builtins/superh/udivsi3.S | 24 +
llvm/include/llvm/IR/RuntimeLibcalls.td | 24 +
llvm/lib/Target/SuperH/CMakeLists.txt | 1 +
.../SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 9 +
llvm/lib/Target/SuperH/SuperH.h | 3 +
llvm/lib/Target/SuperH/SuperHCallingConv.td | 19 +-
.../Target/SuperH/SuperHFillDelaySlots.cpp | 138 ++++++
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 185 +++++++-
llvm/lib/Target/SuperH/SuperHFrameLowering.h | 2 +-
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 4 +-
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 289 +++++++++++-
llvm/lib/Target/SuperH/SuperHISelLowering.h | 9 +
llvm/lib/Target/SuperH/SuperHInstrDSP.td | 12 +
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 69 +--
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 3 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 432 ++++++++++++++++--
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 35 +-
llvm/lib/Target/SuperH/SuperHRegisterInfo.h | 8 +-
llvm/lib/Target/SuperH/SuperHRegisterInfo.td | 7 +-
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 6 +
25 files changed, 1250 insertions(+), 149 deletions(-)
create mode 100644 compiler-rt/lib/builtins/superh/divhi3.S
create mode 100644 compiler-rt/lib/builtins/superh/divqi3.S
create mode 100644 compiler-rt/lib/builtins/superh/divsi3.S
create mode 100644 compiler-rt/lib/builtins/superh/udivhi3.S
create mode 100644 compiler-rt/lib/builtins/superh/udivqi3.S
create mode 100644 compiler-rt/lib/builtins/superh/udivsi3.S
create mode 100644 llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHInstrDSP.td
diff --git a/compiler-rt/lib/builtins/superh/divhi3.S b/compiler-rt/lib/builtins/superh/divhi3.S
new file mode 100644
index 0000000000000..4e63a33a1d715
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/divhi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+ .macro FUNCTION_BEGIN name
+ .text
+ .p2align 4
+ .globl \name
+ .type \name, @function
+\name:
+ .endm
+
+ .macro FUNCTION_END name
+ .size \name, . - \name
+ .endm
+
+
+FUNCTION_BEGIN __sh_divhi3
+
+FUNCTION_END __sh_divhi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/divqi3.S b/compiler-rt/lib/builtins/superh/divqi3.S
new file mode 100644
index 0000000000000..cb73cadb22103
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/divqi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+ .macro FUNCTION_BEGIN name
+ .text
+ .p2align 4
+ .globl \name
+ .type \name, @function
+\name:
+ .endm
+
+ .macro FUNCTION_END name
+ .size \name, . - \name
+ .endm
+
+
+FUNCTION_BEGIN __sh_divqi3
+
+FUNCTION_END __sh_divqi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/divsi3.S b/compiler-rt/lib/builtins/superh/divsi3.S
new file mode 100644
index 0000000000000..07da658506941
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/divsi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+ .macro FUNCTION_BEGIN name
+ .text
+ .p2align 4
+ .globl \name
+ .type \name, @function
+\name:
+ .endm
+
+ .macro FUNCTION_END name
+ .size \name, . - \name
+ .endm
+
+
+FUNCTION_BEGIN __sh_divsi3
+
+FUNCTION_END __sh_divsi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivhi3.S b/compiler-rt/lib/builtins/superh/udivhi3.S
new file mode 100644
index 0000000000000..4eda163340250
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/udivhi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+ .macro FUNCTION_BEGIN name
+ .text
+ .p2align 4
+ .globl \name
+ .type \name, @function
+\name:
+ .endm
+
+ .macro FUNCTION_END name
+ .size \name, . - \name
+ .endm
+
+
+FUNCTION_BEGIN __sh_udivhi3
+
+FUNCTION_END __sh_udivhi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivqi3.S b/compiler-rt/lib/builtins/superh/udivqi3.S
new file mode 100644
index 0000000000000..1c03576115a40
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/udivqi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+ .macro FUNCTION_BEGIN name
+ .text
+ .p2align 4
+ .globl \name
+ .type \name, @function
+\name:
+ .endm
+
+ .macro FUNCTION_END name
+ .size \name, . - \name
+ .endm
+
+
+FUNCTION_BEGIN __sh_udivqi3
+
+FUNCTION_END __sh_udivqi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivsi3.S b/compiler-rt/lib/builtins/superh/udivsi3.S
new file mode 100644
index 0000000000000..22386367f52ba
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/udivsi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+ .macro FUNCTION_BEGIN name
+ .text
+ .p2align 4
+ .globl \name
+ .type \name, @function
+\name:
+ .endm
+
+ .macro FUNCTION_END name
+ .size \name, . - \name
+ .endm
+
+
+FUNCTION_BEGIN __sh_udivsi3
+
+FUNCTION_END __sh_udivsi3
\ No newline at end of file
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 37bad559f49e7..0913a6826946c 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -3324,6 +3324,30 @@ def SPARCSystemLibrary
AvailableIf<__stack_chk_guard, isNotOSLinuxAndNotOSOpenBSD>)
>;
+//===----------------------------------------------------------------------===//
+// SuperH Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+defset list<RuntimeLibcallImpl> SuperHRuntimeLibcalls = {
+def __sh_divqi3 : RuntimeLibcallImpl<SDIV_I8>;
+def __sh_divhi3 : RuntimeLibcallImpl<SDIV_I16>;
+def __sh_divsi3 : RuntimeLibcallImpl<SDIV_I32>;
+def __sh_udivqi3 : RuntimeLibcallImpl<UDIV_I8>;
+def __sh_udivhi3 : RuntimeLibcallImpl<UDIV_I16>;
+def __sh_udivsi3 : RuntimeLibcallImpl<UDIV_I32>;
+}
+
+defvar SuperH_DivCalls = [
+ __divqi3, __divhi3, __divsi3, __udivqi3, __udivhi3, __udivsi3
+];
+
+def isSuperH : RuntimeLibcallPredicate<"TT.isSuperH()">;
+def SuperHSystemLibrary
+ : SystemRuntimeLibrary<isSuperH,
+ (add (sub DefaultLibcallImpls32, SuperH_DivCalls),
+ LibcallImpls<(add SuperHRuntimeLibcalls)>)
+>;
+
//===----------------------------------------------------------------------===//
// SPIRV Runtime Libcalls
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index 535e9d53b2853..a67293ce502f4 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -27,6 +27,7 @@ add_llvm_target(SuperHCodeGen
SuperHAsmPrinter.cpp
SuperHInstrInfo.cpp
SuperHSubtarget.cpp
+ SuperHFillDelaySlots.cpp
LINK_COMPONENTS
Analysis
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 3ddbb766796f1..987b0594cf813 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -13,7 +13,9 @@
#include "SuperHInstPrinter.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
@@ -53,6 +55,13 @@ void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostrea
O << Op.getImm();
return;
}
+
+ // Print symbol references
+ if (Op.isBareSymbolRef()) {
+ const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
+ O << SymOp->getSymbol().getName();
+ return;
+ }
}
void SuperHInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index 75fdde6c8b6a0..c0d62f8fb03f8 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -26,9 +26,12 @@ class PassRegistry;
class SuperHTargetMachine;
FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel);
+FunctionPass *createSuperHFillDelaySlotsPass();
void initializeSuperHDAGToDAGISelLegacyPass(PassRegistry &);
void initializeSuperHAsmPrinterPass(PassRegistry &);
+void initializeSuperHAsmPrinterPass(PassRegistry &);
+void initializeSuperHFillDelaySlotsPass(PassRegistry &);
} // namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index 6ce14d5d0c8a9..429bd8be41908 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -13,20 +13,23 @@
//===-------------------------------------------------------------------------===//
def CC_SH : CallingConv<[
- CCIfSRet<CCCustom<"RetCC_SuperH_SRet">>,
- // Handles byval parameters.
- CCIfByVal<CCPassByVal<4, 4>>,
+ // All lower size parameters are promoted to 32-bit
CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
-
CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
- CCIfType<[i32], CCAssignToStack<4, 4>>,
- CCIfType<[f32], CCAssignToStack<4, 4>>,
]>;
def RetCC_SH : CallingConv<[
- CCIfType<[i32], CCAssignToReg<[R0]>>,
- CCIfType<[i64], CCAssignToReg<[R0, R1]>>
+ CCIfSRet<CCCustom<"RetCC_SuperH_SRet">>,
+
+ // All lower size parameters are promoted to 32-bit
+ CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+ CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>,
+ CCIfType<[i64], CCAssignToReg<[R0, R1]>>,
+
+ // Anything that doesn't fit in registers should be spilled.
+ CCIfType<[i32], CCAssignToStack<4, 4>>,
+ CCIfType<[i64], CCAssignToStack<8, 8>>,
]>;
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
new file mode 100644
index 0000000000000..f96038e3b9cb7
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -0,0 +1,138 @@
+//===-- SuperHFillDelaySlots.cpp - Reordering pass to fill delay slots ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that fills delay slots of branching instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperH.h"
+#include "SuperHInstrInfo.h"
+#include "SuperHTargetMachine.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/Support/DebugLog.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-fill-delay-slots"
+#define SUPERH_FILL_DELAY_SLOTS_NAME "SuperH delay slot filling pass"
+
+namespace {
+class SuperHFillDelaySlots : public MachineFunctionPass {
+public:
+ static char ID;
+
+ SuperHFillDelaySlots() : MachineFunctionPass(ID) {}
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ StringRef getPassName() const override { return SUPERH_FILL_DELAY_SLOTS_NAME; }
+
+private:
+ typedef MachineBasicBlock Block;
+ typedef Block::iterator BlockIt;
+
+ const SuperHRegisterInfo *TRI;
+ const TargetInstrInfo *TII;
+
+ bool hasDelaySlot(MachineInstr &I);
+ bool expandMBB(Block &MBB);
+ bool expandMI(Block &MBB, BlockIt MBBI);
+
+ // Expansion functions
+ bool fillDelaySlot(Block &MBB, BlockIt MBBI);
+};
+
+} // end namespace
+
+
+bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
+ MachineInstr &MI = *MBBI;
+ if (auto *Prev = MBBI->getPrevNode()) {
+
+ // If the prior instruction does not have a delay slot
+ // we swap the instructions.
+ //
+ // NOTE: SuperH does not allow branch instructions
+ // of any kind to be situated in a delay slot.
+ // as such we fall through to the NOP in that
+ // instance.
+ if (!Prev->isBranch() && !Prev->hasDelaySlot()) {
+ LDBG() << "Swapping " << TII->getName(MI.getOpcode())
+ << " and " << TII->getName(Prev->getOpcode())
+ << " @ " << MBB.getParent()->getName();
+ MBB.insertAfter(MBBI, Prev->removeFromParent());
+ return true;
+ }
+ }
+
+ LDBG() << "Inserting NOP after " << TII->getName(MI.getOpcode())
+ << " @ " << MBB.getParent()->getName();
+
+ // Otherwise just insert a NOP.
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(SH::NOP));
+ return true;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// HELPERS
+//===----------------------------------------------------------------------===//
+
+bool SuperHFillDelaySlots::expandMI(Block &MBB, BlockIt MBBI) {
+ MachineInstr &MI = *MBBI;
+
+ if (MI.hasDelaySlot()) {
+ return fillDelaySlot(MBB, MBBI);
+ }
+ return false;
+}
+
+bool SuperHFillDelaySlots::expandMBB(Block &MBB) {
+ bool Modified = false;
+
+ BlockIt MBBI = MBB.begin(), E = MBB.end();
+ while (MBBI != E) {
+ BlockIt NMBBI = std::next(MBBI);
+ Modified |= expandMI(MBB, MBBI);
+ MBBI = NMBBI;
+ }
+
+ return Modified;
+}
+
+bool SuperHFillDelaySlots::runOnMachineFunction(MachineFunction &MF) {
+ bool Modified = false;
+
+ const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+ TRI = STI.getRegisterInfo();
+ TII = STI.getInstrInfo();
+
+ for (Block &MBB : MF) {
+ Modified |= expandMBB(MBB);
+ }
+
+ return Modified;
+}
+
+
+char SuperHFillDelaySlots::ID = 0;
+
+INITIALIZE_PASS(SuperHFillDelaySlots, "sh-fill-delay-slots", SUPERH_FILL_DELAY_SLOTS_NAME,
+ false, false)
+
+FunctionPass *llvm::createSuperHFillDelaySlotsPass() {
+ return new SuperHFillDelaySlots();
+}
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index a96ea010c27ab..5db9816b1ca2d 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -13,42 +13,203 @@
#include "SuperHFrameLowering.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "SuperHInstrInfo.h"
+#include "SuperHRegisterInfo.h"
#include "SuperHSubtarget.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugLog.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define DEBUG_TYPE "sh-framelowering"
using namespace llvm;
-void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+// Get amount of times to shift the value in a SP adjustment
+// for it to fit.
+static unsigned getShiftAmt(uint32_t Val) {
+ unsigned R = 0;
+ for(unsigned i = 0; i < 4; i++) {
+ if (((Val >> (i*8)) & 0xFF))
+ R = i;
+ }
+ return R;
+}
+
+// Helper to emit stack pointer adjustment.
+static void emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int32_t AdjValue) {
+ DebugLoc dl;
+ const SuperHInstrInfo &TII = *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
+ const SuperHRegisterInfo &RII = *static_cast<const SuperHRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
+ MachineInstr::MIFlag MFlag = AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
+
+ Register SP = RII.getStackRegister();
+
+ if (AdjValue < 255) {
+
+ // Fast path, emit a single immediate add.
+ // Emit add #-(size),r15
+ BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
+ .addImm((int)AdjValue)
+ .addReg(SP);
- // If function is naked, don't emit prologue.
- if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
return;
}
+ // Slow path, shift 8 bits at a time into r0.
+ unsigned ToShift = getShiftAmt(AdjValue);
+
+ // Empty R0 in case it had something.
+ BuildMI(MBB, MBBI, dl, TII.get(SH::MOVI8Rn), SH::R0)
+ .addImm(0)
+ .addReg(SH::R0)
+ .setMIFlag(MFlag);
+
+ // Shift value in with the following pattern:
+ // or #(byte), r0
+ // shll8 r0
+ for(unsigned i = 0; i < ToShift; i++) {
+ BuildMI(MBB, MBBI, dl, TII.get(SH::ORI8R0))
+ .addImm((AdjValue >> (i*8)) & 0xFF)
+ .setMIFlag(MFlag);
+ BuildMI(MBB, MBBI, dl, TII.get(SH::SHLL8Rn), SH::R0)
+ .addReg(SH::R0)
+ .setMIFlag(MFlag);
+ }
+
+ // Finally negate and add to r15.
+ // neg r0, r0 (if negative displacement)
+ // add r0, r15
+ if (AdjValue < 0)
+ BuildMI(MBB, MBBI, dl, TII.get(SH::NEGRmRn), SH::R0)
+ .addReg(SH::R0)
+ .addReg(SH::R0)
+ .setMIFlag(MFlag);
+
+ BuildMI(MBB, MBBI, dl, TII.get(SH::SUBRmRn), SP)
+ .addReg(SH::R0, RegState::Kill)
+ .addReg(SP)
+ .setMIFlag(MFlag);
+}
+
+void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+ MachineBasicBlock::iterator MBBI = MBB.begin();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+ const SuperHInstrInfo &TII = *STI.getInstrInfo();
+ const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+ DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
+ bool HasFP = hasFP(MF);
+
+ Register SP = RII.getStackRegister();
+ Register FP = RII.getFrameRegister();
+
+ LDBG() << "emitPrologue";
+
+ // Realign stack
+ uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
+ MFI.setStackSize(StackSize);
+
+ // 1. Create stack frame
+ emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
+
+ // TODO: Create working register set.
+
+ // 3. Save return address to stack.
+ BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
+
+ // 4. Establish frame pointer
+ if (HasFP) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+
+ // TODO: Establish GCP?
}
void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+ const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+ Register SP = RII.getStackRegister();
+ Register FP = RII.getFrameRegister();
+
+ LDBG() << "emitEpilogue";
- // If function is naked, don't emit epilogue.
- if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
+ // Early exit if we have no frame pointer.
+ if (!hasFP(MF)) {
return;
}
+
+
+ MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ DebugLoc DL = MBBI->getDebugLoc();
+ const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+ const SuperHInstrInfo &TII = *STI.getInstrInfo();
+
+ uint32_t StackSize = MFI.getStackSize();
+
+ // TODO: Restore callee save registers
+
+ // 2. Restore return address from stack
+ BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+
+ // 3. Delete stack frame, restoring stack pointer.
+ emitSPAdj(MF, MBB, MBBI, StackSize);
}
-bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+MachineBasicBlock::iterator
+SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
+ MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI) const {
+ const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+ const SuperHInstrInfo &TII = *STI.getInstrInfo();
+
+ LDBG() << "eliminateCallFramePseudoInstr";
+
+ // If call frame is reserved, erase.
+ if (hasReservedCallFrame(MF)) {
+ return MBB.erase(MI);
+ }
+
+ // If frame size is 0, erase.
+ int Amount = TII.getFrameSize(*MI);
+ if (Amount == 0) {
+ return MBB.erase(MI);
+ }
+
+ DebugLoc DL = MI->getDebugLoc();
+ unsigned int Opcode = MI->getOpcode();
+ if (Opcode == TII.getCallFrameSetupOpcode()) {
+ LDBG() << "eliminateCallFramePseudoInstr->CallFrameSetup";
+ } else {
+ LDBG() << "eliminateCallFramePseudoInstr->CallFrameDestroy";
+ assert(Opcode == TII.getCallFrameDestroyOpcode());
+
+ }
+
+ return MBB.erase(MI);
+}
+
+bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
- return hasFP(MF) && !MFI.hasVarSizedObjects();
+ return MF.getTarget().Options.DisableFramePointerElim(MF) ||
+ MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
}
-MachineBasicBlock::iterator
-SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I) const {
- return MBB.erase(I);
+bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ return !MFI.hasVarSizedObjects();
}
void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const {
-
+ TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index c303baa4311d1..dd2cc63aaa32e 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -43,7 +43,7 @@ class SuperHFrameLowering : public TargetFrameLowering {
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const override;
protected:
- bool hasFPImpl(const MachineFunction &MF) const override { return false; }
+ bool hasFPImpl(const MachineFunction &MF) const override;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index d14e187479bb3..5c5f851ec4a72 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -117,7 +117,7 @@ bool SuperHDAGToDAGISel::trySelectRET(SDNode *N) {
Ops.push_back(Chain.getValue(1));
SDNode *ResNode = CurDAG->getMachineNode(SH::RTS, DL, MVT::Other, Ops);
- ResNode = CurDAG->getMachineNode(SH::NOP, DL, MVT::Other, SDValue(ResNode, 0));
+ //ResNode = CurDAG->getMachineNode(SH::NOP, DL, MVT::Other, SDValue(ResNode, 0));
ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
CurDAG->RemoveDeadNode(N);
@@ -140,7 +140,7 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
switch(Opcode) {
case ISD::FrameIndex:
return trySelectFrameIndex(N);
- case SHISD::RET:
+ case SHISD::RET_GLUE:
return trySelectRET(N);
default:
return false;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 46346fe72f9a3..39304e493a23d 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -18,8 +18,11 @@
#include "SuperHTargetMachine.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/FunctionLoweringInfo.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/Support/DebugLog.h"
using namespace llvm;
@@ -47,8 +50,28 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
// GPR Registers are always 32 bit on SuperH.
addRegisterClass(MVT::i32, &SH::GPRRegClass);
+ setSchedulingPreference(Sched::RegPressure);
+ setSupportsUnalignedAtomics(false);
computeRegisterProperties(Subtarget->getRegisterInfo());
+ // Loads and stores are legal
+ for (MVT VT : MVT::integer_valuetypes()) {
+ for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
+ setLoadExtAction(N, VT, MVT::i1, Promote);
+ setLoadExtAction(N, VT, MVT::i8, Promote);
+ setLoadExtAction(N, VT, MVT::i16, Promote);
+ }
+ }
+
+ // Division and remainders are multi-instruction sequences
+ // on SuperH. Use a custom pass to lower those.
+ for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
+ setOperationAction(ISD::UDIV, VT, Custom);
+ setOperationAction(ISD::UREM, VT, Custom);
+ setOperationAction(ISD::SDIV, VT, Custom);
+ setOperationAction(ISD::SREM, VT, Custom);
+ }
+
setBooleanContents(ZeroOrOneBooleanContent);
setBooleanVectorContents(ZeroOrOneBooleanContent);
@@ -132,6 +155,9 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
return Chain;
}
+
+
+
//===----------------------------------------------------------------------===//
// RETURN LOWERING
//===----------------------------------------------------------------------===//
@@ -170,7 +196,7 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
}
- // If function is naked, don't emit rts.
+ // If function is naked, don't emit return glue.
if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
return Chain;
}
@@ -180,14 +206,265 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
if (Glue.getNode())
RetOps.push_back(Glue);
- return DAG.getNode(SHISD::RET, dl, MVT::Other, RetOps);
+ return DAG.getNode(SHISD::RET_GLUE, dl, MVT::Other, RetOps);
}
+
+
+
+//===----------------------------------------------------------------------===//
+// CALL LOWERING
+//===----------------------------------------------------------------------===//
+
SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const {
- for(unsigned i = 0; i < CLI.Ins.size(); i++) {
- auto VArg = CLI.getArgs()[i];
- InVals.push_back(VArg.Node);
+ SelectionDAG &DAG = CLI.DAG;
+ MachineFunction &MF = DAG.getMachineFunction();
+ SDLoc &DL = CLI.DL;
+ SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+ SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
+ SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+ SDValue Chain = CLI.Chain;
+ SDValue Callee = CLI.Callee;
+ bool &isTailCall = CLI.IsTailCall;
+ CallingConv::ID CallConv = CLI.CallConv;
+ bool isVarArg = CLI.IsVarArg;
+
+ // TODO: This was all yoinked from AVR, it likely needs to be modified to fit the calling
+ // convention of SuperH.
+
+ // Tail Call Optimisation not supported yet.
+ isTailCall = false;
+ isVarArg = false;
+
+ // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
+ // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
+ // node so that legalize doesn't hack it.
+ const Function *F = nullptr;
+ if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+ const GlobalValue *GV = G->getGlobal();
+ if (isa<Function>(GV))
+ F = cast<Function>(GV);
+ Callee =
+ DAG.getTargetGlobalAddress(GV, DL, getPointerTy(DAG.getDataLayout()));
+ } else if (const ExternalSymbolSDNode *ES =
+ dyn_cast<ExternalSymbolSDNode>(Callee)) {
+ Callee = DAG.getTargetExternalSymbol(ES->getSymbol(),
+ getPointerTy(DAG.getDataLayout()));
+ }
+
+ if (isVarArg) {
+ return Chain;
+ }
+
+ // Analyze operands of the call, assigning locations to each operand.
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
+ *DAG.getContext());
+
+ // Get a count of how many bytes are to be pushed on the stack.
+ unsigned NumBytes = CCInfo.getStackSize();
+ Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL);
+ SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
+
+ // First, walk the register assignments, inserting copies.
+ unsigned AI, AE;
+ bool HasStackArgs = false;
+ for (AI = 0, AE = ArgLocs.size(); AI != AE; ++AI) {
+ CCValAssign &VA = ArgLocs[AI];
+ EVT RegVT = VA.getLocVT();
+ SDValue Arg = OutVals[AI];
+
+ // Stop when we encounter a stack argument, we need to process them
+ // in reverse order in the loop below.
+ if (VA.isMemLoc()) {
+ HasStackArgs = true;
+ break;
+ }
+
+ // Arguments that can be passed on registers must be kept in the RegsToPass
+ // vector.
+ RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
+ }
+
+ // Second, stack arguments have to walked.
+ // Previously this code created chained stores but those chained stores appear
+ // to be unchained in the legalization phase. Therefore, do not attempt to
+ // chain them here. In fact, chaining them here somehow causes the first and
+ // second store to be reversed which is the exact opposite of the intended
+ // effect.
+ if (HasStackArgs) {
+ SmallVector<SDValue, 8> MemOpChains;
+ for (; AI != AE; AI++) {
+ CCValAssign &VA = ArgLocs[AI];
+ SDValue Arg = OutVals[AI];
+
+ assert(VA.isMemLoc());
+
+ // SP points to one stack slot further so add one to adjust it.
+ SDValue PtrOff = DAG.getNode(
+ ISD::ADD, DL, getPointerTy(DAG.getDataLayout()),
+ DAG.getRegister(SH::R15, getPointerTy(DAG.getDataLayout())),
+ DAG.getIntPtrConstant(VA.getLocMemOffset() + 1, DL));
+
+ MemOpChains.push_back(
+ DAG.getStore(Chain, DL, Arg, PtrOff,
+ MachinePointerInfo::getStack(MF, VA.getLocMemOffset())));
+ }
+
+ if (!MemOpChains.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
+ }
+
+ // Build a sequence of copy-to-reg nodes chained together with token chain and
+ // flag operands which copy the outgoing args into registers. The InGlue in
+ // necessary since all emited instructions must be stuck together.
+ SDValue InGlue;
+ for (auto Reg : RegsToPass) {
+ Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, InGlue);
+ InGlue = Chain.getValue(1);
+ }
+
+ // Returns a chain & a flag for retval copy to use.
+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
+ SmallVector<SDValue, 8> Ops;
+ Ops.push_back(Chain);
+ Ops.push_back(Callee);
+
+ // Add argument registers to the end of the list so that they are known live
+ // into the call.
+ for (auto Reg : RegsToPass) {
+ Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
+ }
+
+ // The zero register (usually R1) must be passed as an implicit register so
+ // that this register is correctly zeroed in interrupts.
+ Ops.push_back(DAG.getRegister(SH::R0, MVT::i32));
+
+ // Add a register mask operand representing the call-preserved registers.
+ const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
+ const uint32_t *Mask =
+ TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
+ assert(Mask && "Missing call preserved mask for calling convention");
+ Ops.push_back(DAG.getRegisterMask(Mask));
+
+ if (InGlue.getNode()) {
+ Ops.push_back(InGlue);
+ }
+
+ Chain = DAG.getNode(SHISD::CALL, DL, NodeTys, Ops);
+ InGlue = Chain.getValue(1);
+
+ // Create the CALLSEQ_END node.
+ Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
+
+ if (!Ins.empty()) {
+ InGlue = Chain.getValue(1);
+ }
+
+ return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, DL, DAG, InVals);
+}
+
+SDValue SuperHTargetLowering::LowerCallResult(
+ SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
+ SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+
+ // Assign locations to each value returned by this call.
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
+ *DAG.getContext());
+
+ // Handle runtime calling convs.
+ CCInfo.AnalyzeCallResult(Ins, RetCC_SH);
+
+ // Copy all of the result registers out of their specified physreg.
+ for (CCValAssign const &RVLoc : RVLocs) {
+ Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(), InGlue)
+ .getValue(1);
+ InGlue = Chain.getValue(2);
+ InVals.push_back(Chain.getValue(0));
}
- return CLI.Chain;
+ return Chain;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// DIVISION LOWERING
+//===----------------------------------------------------------------------===//
+
+SDValue SuperHTargetLowering::LowerDiv(SDValue Op, SelectionDAG &DAG) const {
+ unsigned Opcode = Op->getOpcode();
+ assert((Opcode == ISD::SDIV || Opcode == ISD::UDIV) &&
+ "Invalid opcode for Div lowering");
+ bool IsSigned = (Opcode == ISD::SDIV);
+ EVT VT = Op->getValueType(0);
+ Type *Ty = VT.getTypeForEVT(*DAG.getContext());
+
+ RTLIB::Libcall LC;
+ switch (VT.getSimpleVT().SimpleTy) {
+ default:
+ llvm_unreachable("Unexpected request for libcall!");
+ case MVT::i8:
+ LC = IsSigned ? RTLIB::SDIV_I8 : RTLIB::UDIV_I8;
+ break;
+ case MVT::i16:
+ LC = IsSigned ? RTLIB::SDIV_I16 : RTLIB::UDIV_I16;
+ break;
+ case MVT::i32:
+ LC = IsSigned ? RTLIB::SDIV_I32 : RTLIB::UDIV_I32;
+ break;
+ }
+
+ SDValue InChain = DAG.getEntryNode();
+
+ TargetLowering::ArgListTy Args;
+ for (SDValue const &Value : Op->op_values()) {
+ TargetLowering::ArgListEntry Entry(
+ Value, Value.getValueType().getTypeForEVT(*DAG.getContext()));
+ Entry.IsSExt = IsSigned;
+ Entry.IsZExt = !IsSigned;
+ Args.push_back(Entry);
+ }
+
+ RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
+ if (LCImpl == RTLIB::Unsupported)
+ return SDValue();
+
+ SDValue Callee =
+ DAG.getExternalSymbol(LCImpl, getPointerTy(DAG.getDataLayout()));
+
+ Type *RetTy = (Type *)StructType::get(Ty, Ty);
+
+
+ SDLoc dl(Op);
+ TargetLowering::CallLoweringInfo CLI(DAG);
+ CLI.setDebugLoc(dl)
+ .setChain(InChain)
+ .setLibCallee(DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy,
+ Callee, std::move(Args))
+ .setInRegister()
+ .setSExtResult(IsSigned)
+ .setZExtResult(!IsSigned);
+
+ std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
+ return CallInfo.first;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// CUSTOM LOWERING
+//===----------------------------------------------------------------------===//
+
+SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
+ switch(Op->getOpcode()) {
+ case ISD::UDIV:
+ case ISD::SDIV:
+ return LowerDiv(Op, DAG);
+ }
+ return SDValue();
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 4617740b75c6d..e23143b989fe5 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -38,6 +38,15 @@ class SuperHTargetLowering : public TargetLowering {
const Type *RetTy) const override;
SDValue LowerCall(CallLoweringInfo &/*CLI*/,
SmallVectorImpl<SDValue> &/*InVals*/) const override;
+
+ SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
+
+ // Custom Lowerings
+ SDValue LowerDiv(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerCallResult(
+ SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
+ SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const;
public:
SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
};
diff --git a/llvm/lib/Target/SuperH/SuperHInstrDSP.td b/llvm/lib/Target/SuperH/SuperHInstrDSP.td
new file mode 100644
index 0000000000000..ef23b0eaccdc9
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrDSP.td
@@ -0,0 +1,12 @@
+//===-- SuperHInstrDSP.td - DSP SuperH Instruction Definition --*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-------------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes the DSP extensions for the SuperH Instruction Set.
+///
+//===-------------------------------------------------------------------------===//
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 9b76cd1d4a9b6..8489d91f8ac85 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -52,65 +52,20 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
llvm_unreachable("Impossible reg-to-reg copy");
}
-bool SuperHInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
- unsigned OpCode = MI.getOpcode();
- switch(OpCode) {
- case SH::DIVURmRn:
- case SH::DIVSRmRn:
- return expandDIV(OpCode, MI);
- default:
- return false;
- }
-}
-
-
+bool SuperHInstrInfo::expandRET(MachineInstr &MI) const {
+ MachineBasicBlock &MBB = *MI.getParent();
+ MachineBasicBlock::iterator MBBI = MI.getIterator();
+ DebugLoc DL = MI.getDebugLoc();
+ BuildMI(MBB, MBBI, DL, get(SH::NOP));
+ return true;
+}
-//===----------------------------------------------------------------------===//
-// Pseudo Instruction Expansion
-//===----------------------------------------------------------------------===//
-
-// Expands the division psuedo instructions into valid SuperH sequences.
-// SuperH sets the division mode with an struction inserted before.
-bool SuperHInstrInfo::expandDIV(unsigned Opcode, MachineInstr &MI) const {
- assert(MI.getOperand(0).isReg() && "Expected register in op0 for expansion!");
- assert(MI.getOperand(1).isReg() && "Expected register in op1 for expansion!");
- auto &MBB = *MI.getParent();
- auto Lhs = MI.getOperand(0).getReg();
- auto Rhs = MI.getOperand(1).getReg();
- auto DL = MI.getDebugLoc();
-
- switch(Opcode) {
-
- // Expand DIVURmRn to the following sequence:
- // div0u
- // div1 Rm, Rn
- case SH::DIVURmRn: {
- BuildMI(MBB, MI, DL, get(SH::DIV0U));
- BuildMI(MBB, MI, DL, get(SH::DIV1RmRn), Rhs)
- .addReg(Lhs);
- MI.removeFromParent();
- return true;
- }
-
- // Expand DIVSRmRn to the following sequence:
- // div0s Rm, Rn
- // div1 Rm, Rn
- case SH::DIVSRmRn: {
- BuildMI(MBB, MI, DL, get(SH::DIV0SRmRn))
- .addReg(Rhs)
- .addReg(Lhs);
- BuildMI(MBB, MI, DL, get(SH::DIV1RmRn), Rhs)
- .addReg(Lhs);
- MI.removeFromParent();
- return true;
- }
-
- // This shouldn't be reached.
- default: {
- llvm_unreachable("expandDIV was wrongfully called on a non-div pseudo!");
- return false;
- }
+bool SuperHInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
+ switch(MI.getOpcode()) {
+ case SH::RTS:
+ return expandRET(MI);
}
+ return false;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index ae47b75d7ffc0..bbd95d0148c89 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -44,7 +44,8 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
bool expandPostRAPseudo(MachineInstr &MI) const override;
private:
- bool expandDIV(unsigned Opcode, MachineInstr &MI) const;
+ // Custom expansions
+ bool expandRET(MachineInstr &MI) const;
};
const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 4a8414f16f11a..32f27707ddf78 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -63,7 +63,7 @@ def SHCall : SDNode<"SHISD::CALL", SHSDT_Call,
[SDNPHasChain, SDNPOutGlue,
SDNPOptInGlue, SDNPVariadic]>;
-def SHRet : SDNode<"SHISD::RET", SDTNone,
+def SHRetGlue : SDNode<"SHISD::RET_GLUE", SDTNone,
[SDNPHasChain, SDNPOptInGlue,
SDNPVariadic]>;
@@ -503,33 +503,34 @@ let hasSideEffects = 0, mayStore = 1 in {
// Addition
//===--------------------------------------------------------------------------===//
-let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+let hasSideEffects = 0, Constraints = "$src = $Rn" in {
// add Rm, Rn
+ let isCommutable = 1 in
def ADDRmRn : InstRmRn<0b0011000000001100,
- (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"add $Rm,$Rn",
- [(set i32:$Rn, (add i32:$src, i32:$Rm))]>;
+ [(set i32:$Rn, (add i32:$Rm, i32:$src))]>;
// add imm:8, Rn
def ADDI8Rn : InstRnI8<0b0011000000001100,
- (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
+ (outs GPR:$Rn), (ins imm8:$imm, GPR:$src),
"add #$imm,$Rn",
- [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
+ [(set i32:$Rn, (add imm8:$imm, i32:$src))]>;
// addc Rm, Rn
- let Defs = [SR], Uses = [SR] in
+ let Defs = [SR], Uses = [SR], isCommutable = 1 in
def ADDCRmRn : InstRmRn<0b0011000000001110,
- (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"addc $Rm,$Rn",
- [(set i32:$Rn, (adde i32:$src, i32:$Rm))]>;
+ [(set i32:$Rn, (adde i32:$Rm, i32:$src))]>;
// addv Rm, Rn
- let Defs = [SR] in
+ let Defs = [SR], isCommutable = 1 in
def ADDVRmRn : InstRmRn<0b0011000000001111,
- (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"addv $Rm,$Rn",
- [(set i32:$Rn, (addc i32:$src, i32:$Rm))]>;
+ [(set i32:$Rn, (addc i32:$Rm, i32:$src))]>;
}
@@ -543,23 +544,23 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// sub Rm, Rn
def SUBRmRn : InstRmRn<0b0011000000001000,
- (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"sub $Rm,$Rn",
- [(set i32:$Rn, (sub i32:$src, i32:$Rm))]>;
+ [(set i32:$Rn, (sub i32:$Rm, i32:$src))]>;
// subc Rm, Rn
let Defs = [SR], Uses = [SR] in
def SUBCRmRn : InstRmRn<0b0011000000001010,
- (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"subc $Rm,$Rn",
- [(set i32:$Rn, (sube i32:$src, i32:$Rm))]>;
+ [(set i32:$Rn, (sube i32:$Rm, i32:$src))]>;
// subv Rm, Rn
let Defs = [SR] in
def SUBVRmRn : InstRmRn<0b0011000000001011,
- (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"subv $Rm,$Rn",
- [(set i32:$Rn, (subc i32:$src, i32:$Rm))]>;
+ [(set i32:$Rn, (subc i32:$Rm, i32:$src))]>;
// dt Rn
let Defs = [SR] in
@@ -597,7 +598,7 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// mul.l Rm, Rn
let Defs = [MACL] in
def MULRmRn : InstRmRn<0b0000000000000111,
- (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"mul.l $Rm,$Rn",
[]>;
@@ -622,7 +623,7 @@ let hasSideEffects = 0, isCommutable = 1 in {
// div0s Rm, Rn
let Defs = [SR] in
def DIV0SRmRn : InstRmRn<0b0010000000000111,
- (outs), (ins GPR:$Rn, GPR:$Rm),
+ (outs), (ins GPR:$Rm, GPR:$Rn),
"div0s $Rm,$Rn",
[]>;
@@ -641,25 +642,6 @@ let hasSideEffects = 0, isCommutable = 1 in {
[]>;
}
-let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
-
- // Expand LLVM sdiv to the following sequence:
- // div0s
- // div1 Rm, Rn
- def DIVSRmRn : SHPseudo<(outs GPR:$Rn),
- (ins GPR:$Rm, GPR:$src),
- "; divs $Rm, $Rn",
- [(set i32:$Rn, (sdiv i32:$Rm, i32:$src))]>;
-
- // Expand LLVM udiv to the following sequence:
- // div0u
- // div1 Rm, Rn
- def DIVURmRn : SHPseudo<(outs GPR:$Rn),
- (ins GPR:$Rm, GPR:$src),
- "; divu $Rm, $Rn",
- [(set i32:$Rn, (udiv i32:$Rm, i32:$src))]>;
-}
-
@@ -742,6 +724,68 @@ def CMPSTRRmRn : InstRmRn<0b0010000000001100,
//===--------------------------------------------------------------------------===//
+let hasSideEffects = 0 in {
+
+ // and Rm,Rn
+ let Constraints = "$src = $Rn" in
+ def ANDRmRn : InstRmRn<0b0010000000001001,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "and $Rm,$Rn",
+ []>;
+ // and #imm,R0
+ let Defs = [R0], Uses = [R0] in
+ def ANDI8R0 : InstI8<0b1100100100000000,
+ (outs), (ins imm8:$imm),
+ "and #$imm,R0",
+ []>;
+
+ // not Rm,Rn
+ let Constraints = "$src = $Rn" in
+ def NOTRmRn : InstRmRn<0b0110000000000111,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "not $Rm,$Rn",
+ []>;
+
+ // or Rm,Rn
+ let Constraints = "$src = $Rn" in
+ def ORRmRn : InstRmRn<0b0010000000001011,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "or $Rm,$Rn",
+ []>;
+ // or #imm,R0
+ let Defs = [R0], Uses = [R0] in
+ def ORI8R0 : InstI8<0b1100101100000000,
+ (outs), (ins imm8:$imm),
+ "or #$imm,R0",
+ []>;
+
+ // xor Rm,Rn
+ let Constraints = "$src = $Rn" in
+ def XORRmRn : InstRmRn<0b0010000000001010,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "xor $Rm,$Rn",
+ []>;
+ // xor #imm,R0
+ let Defs = [R0], Uses = [R0] in
+ def XORI8R0 : InstI8<0b1100101000000000,
+ (outs), (ins imm8:$imm),
+ "xor #$imm,R0",
+ []>;
+
+ // tst Rm,Rn
+ let Defs = [SR], Constraints = "$src = $Rn" in
+ def TSTRmRn : InstRmRn<0b0010000000001000,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "tst $Rm,$Rn",
+ []>;
+ // tst #imm,R0
+ let Defs = [R0, SR], Uses = [R0] in
+ def TSTI8R0 : InstI8<0b1100100000000000,
+ (outs), (ins imm8:$imm),
+ "tst #$imm,R0",
+ []>;
+
+}
@@ -752,7 +796,102 @@ def CMPSTRRmRn : InstRmRn<0b0010000000001100,
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
+let hasSideEffects = 0, Constraints = "$src = $Rn" in {
+
+ // rotcl Rn
+ let Defs = [SR] in
+ def ROTCLRn : InstRn<0b0100000000100100,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "rotcl $Rn",
+ []>;
+
+ // rotcr Rn
+ let Defs = [SR] in
+ def ROTCRRn : InstRn<0b0100000000100101,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "rotcr $Rn",
+ []>;
+
+ // rotl Rn
+ let Defs = [SR] in
+ def ROTLRn : InstRn<0b0100000000000100,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "rotl $Rn",
+ []>;
+
+ // rotr Rn
+ let Defs = [SR] in
+ def ROTRRn : InstRn<0b0100000000000101,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "rotr $Rn",
+ []>;
+
+ // shal Rn
+ let Defs = [SR] in
+ def SHALRn : InstRn<0b0100000000100000,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shal $Rn",
+ []>;
+
+ // shar Rn
+ let Defs = [SR] in
+ def SHARRn : InstRn<0b0100000000100001,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shar $Rn",
+ []>;
+
+ // shll Rn
+ let Defs = [SR] in
+ def SHLLRn : InstRn<0b0100000000000000,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shll $Rn",
+ []>;
+
+ // shll2 Rn
+ let Defs = [SR] in
+ def SHLL2Rn : InstRn<0b0100000000001000,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shll2 $Rn",
+ []>;
+
+ // shll8 Rn
+ def SHLL8Rn : InstRn<0b0100000000011000,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shll8 $Rn",
+ []>;
+
+ // shll16 Rn
+ def SHLL16Rn : InstRn<0b0100000000101000,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shll16 $Rn",
+ []>;
+
+ // shlr Rn
+ let Defs = [SR] in
+ def SHLRRn : InstRn<0b0100000000000001,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shlr $Rn",
+ []>;
+
+ // shlr2 Rn
+ def SHLR2Rn : InstRn<0b0100000000001001,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shlr2 $Rn",
+ []>;
+
+ // shlr8 Rn
+ def SHLR8Rn : InstRn<0b0100000000011001,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shlr8 $Rn",
+ []>;
+
+ // shlr16 Rn
+ def SHLR16Rn : InstRn<0b0100000000101001,
+ (outs GPR:$Rn), (ins GPR:$src),
+ "shlr16 $Rn",
+ []>;
+}
//===--------------------------------------------------------------------------===//
@@ -790,8 +929,8 @@ let isCall = 1 in {
// Return Instructions
//===--------------------------------------------------------------------------===//
-let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
- def RTS : Inst<0b0000000000001011,
+let isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1 in {
+ def RTS : Inst<0b0000000000001011,
(outs), (ins),
"rts",
[]>;
@@ -807,32 +946,229 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
+// clrmac
+def CLRMAC : Inst<0b0000000000101000, (outs), (ins), "clrmac", []>;
+
+// clrt
+let Defs = [SR] in
+def CLRT : Inst<0b0000000000001000, (outs), (ins), "clrt", []>;
+
+// ldc Rm, SR
+let Defs = [SR] in
+def LDCRmSR : InstRm<0b0100000000001110,
+ (outs), (ins GPR:$Rm),
+ "ldc $Rm,SR",
+ []>;
+// ldc.l @Rm+, SR
+let Defs = [SR] in
+def LDCLRminciSR : InstRm<0b0100000000000111,
+ (outs), (ins GPR:$Rm),
+ "ldc.l @$Rm+,SR",
+ []>;
+// ldc Rm, GBR
+let Defs = [GBR] in
+def LDCRmGBR : InstRm<0b0100000000011110,
+ (outs), (ins GPR:$Rm),
+ "ldc $Rm,GBR",
+ []>;
+// ldc.l @Rm+, GBR
+let Defs = [GBR] in
+def LDCLRminciGBR : InstRm<0b0100000000010111,
+ (outs), (ins GPR:$Rm),
+ "ldc.l @$Rm+,GBR",
+ []>;
-//===--------------------------------------------------------------------------===//
-// Control Instructions
-//===--------------------------------------------------------------------------===//
+// ldc Rm, VBR
+let Defs = [VBR] in
+def LDCRmVBR : InstRm<0b0100000000101110,
+ (outs), (ins GPR:$Rm),
+ "ldc $Rm,VBR",
+ []>;
+
+// ldc.l @Rm+, VBR
+let Defs = [VBR] in
+def LDCLRminciVBR : InstRm<0b0100000000100111,
+ (outs), (ins GPR:$Rm),
+ "ldc.l @$Rm+,VBR",
+ []>;
+
+// lds Rm, MACH
+let Defs = [MACH] in
+def LDSRmMACH : InstRm<0b0100000000001010,
+ (outs), (ins GPR:$Rm),
+ "lds $Rm,MACH",
+ []>;
+
+// lds.l @Rm+, MACH
+let Defs = [MACH] in
+def LDSLRminciMACH : InstRm<0b0100000000000110,
+ (outs), (ins GPR:$Rm),
+ "lds.l @$Rm+,MACH",
+ []>;
+
+// lds Rm, MACL
+let Defs = [MACH] in
+def LDSRmMACL : InstRm<0b0100000000011010,
+ (outs), (ins GPR:$Rm),
+ "lds $Rm,MACL",
+ []>;
+
+// lds.l @Rm+, MACL
+let Defs = [MACH] in
+def LDSLRminciMACL : InstRm<0b0100000000010110,
+ (outs), (ins GPR:$Rm),
+ "lds.l @$Rm+,MACL",
+ []>;
+
+// lds Rm, PR
+let Defs = [PR] in
+def LDSRmPR : InstRm<0b0100000000101010,
+ (outs), (ins GPR:$Rm),
+ "lds $Rm,PR",
+ []>;
+
+// lds.l @Rm+, PR
+let Defs = [PR] in
+def LDSLRminciPR : InstRm<0b0100000000100110,
+ (outs), (ins GPR:$Rm),
+ "lds.l @$Rm+,PR",
+ []>;
// nop
let hasSideEffects = 1 in
-def NOP : Inst<0b0000000000001001, (outs), (ins), "nop", []>;
+def NOP : Inst<0b0000000000001001, (outs), (ins), "nop", []>;
+
+// rte
+let isTerminator = 1, isReturn = 1, isBranch = 1, hasDelaySlot = 1 in
+def RTE : Inst<0b0000000000101011, (outs), (ins), "rte", []>;
+
+// sett
+let Defs = [SR] in
+def SETT : Inst<0b0000000000011000, (outs), (ins), "sett", []>;
// sleep
let hasSideEffects = 1 in
-def SLEEP : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
+def SLEEP : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
+// stc SR,Rn
+let Uses = [SR] in
+def STCSRRn : InstRn<0b0000000000000010,
+ (outs GPR:$Rn), (ins),
+ "stc SR,$Rn",
+ []>;
+// stc.l SR, at -Rn
+let Uses = [SR] in
+def STCLSRRndeci : InstRn<0b0100000000000011,
+ (outs GPR:$Rn), (ins),
+ "stc.l SR, at -$Rn",
+ []>;
+
+// stc GBR,Rn
+let Uses = [GBR] in
+def STCGBRRn : InstRn<0b0000000000010010,
+ (outs GPR:$Rn), (ins),
+ "stc GBR,$Rn",
+ []>;
+
+// stc.l GBR, at -Rn
+let Uses = [GBR] in
+def STCLGBRRndeci : InstRn<0b0100000000010011,
+ (outs GPR:$Rn), (ins),
+ "stc.l GBR, at -$Rn",
+ []>;
+
+// stc VBR,Rn
+let Uses = [VBR] in
+def STCVBRRn : InstRn<0b0000000000100010,
+ (outs GPR:$Rn), (ins),
+ "stc VBR,$Rn",
+ []>;
+
+// stc.l VBR, at -Rn
+let Uses = [VBR] in
+def STCLVBRRndeci : InstRn<0b0100000000100011,
+ (outs GPR:$Rn), (ins),
+ "stc.l VBR, at -$Rn",
+ []>;
+
+// sts MACH,Rn
+let Uses = [MACH] in
+def STSMACHRn : InstRn<0b0000000000001010,
+ (outs GPR:$Rn), (ins),
+ "sts MACH,$Rn",
+ []>;
+
+// sts.l MACH, at -Rn
+let Uses = [MACH] in
+def STSLMACHRndeci : InstRn<0b0100000000000010,
+ (outs GPR:$Rn), (ins),
+ "sts.l MACH, at -$Rn",
+ []>;
+
+// sts MACL,Rn
+let Uses = [MACL] in
+def STSMACLRn : InstRn<0b0000000000011010,
+ (outs GPR:$Rn), (ins),
+ "sts MACL,$Rn",
+ []>;
+
+// sts.l MACL, at -Rn
+let Uses = [MACL] in
+def STSLMACLRndeci : InstRn<0b0100000000010010,
+ (outs GPR:$Rn), (ins),
+ "sts.l MACL, at -$Rn",
+ []>;
+
+// sts PR,Rn
+let Uses = [PR] in
+def STSPRRn : InstRn<0b0000000000101010,
+ (outs GPR:$Rn), (ins),
+ "sts PR,$Rn",
+ []>;
+
+// sts.l PR, at -Rn
+let Uses = [PR] in
+def STSLPRRndeci : InstRn<0b0100000000100010,
+ (outs GPR:$Rn), (ins),
+ "sts.l PR, at -$Rn",
+ []>;
+
+// trapa #imm
+let Defs = [PC], isCall = 1 in
+def TRAPAI8 : InstI8<0b1100001100000000,
+ (outs), (ins imm8:$imm),
+ "trapa #$imm",
+ []>;
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Extensions
//===--------------------------------------------------------------------------===//
-// Bigger Extensions
//===--------------------------------------------------------------------------===//
include "SuperHInstrDSP.td"
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Pseudo instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+
+
+
//===--------------------------------------------------------------------------===//
-// Pseudo instructions
+// Stack Frame
//===--------------------------------------------------------------------------===//
// Helper instruction for mapping frame indices to relative frame pointer
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index a8781f921dcac..f6053dbb48798 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -19,6 +19,7 @@
#include "SuperH.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
@@ -38,10 +39,6 @@ const TargetRegisterClass *SuperHRegisterInfo::getPointerRegClass(unsigned Kind)
return &SH::GPRRegClass;
}
-const TargetRegisterClass *SuperHRegisterInfo::intRegClass(unsigned Size) const {
- return &SH::GPRRegClass;
-}
-
const MCPhysReg *SuperHRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_SH_SaveList;
}
@@ -50,15 +47,31 @@ const uint32_t *SuperHRegisterInfo::getCallPreservedMask(const MachineFunction &
return CSR_SH_RegMask;
}
+const TargetRegisterClass *
+SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
+ const MachineFunction &MF) const {
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+
+ if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
+ return &SH::GPRRegClass;
+ }
+
+ if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
+ return &SH::GPRRegClass;
+ }
+
+ return TargetRegisterInfo::getLargestLegalSuperClass(RC, MF);
+}
+
BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
- // R0 and R1 are always reserved as return slots.
+ // R0 is always reserved as some instructions can only write to it.
Reserved.set(SH::R0);
- Reserved.set(SH::R1);
- // Also reserve the stack frame.
+ // Also reserve the stack frame and stack pointer.
Reserved.set(SH::R14);
+ Reserved.set(SH::R15);
return Reserved;
}
@@ -95,4 +108,12 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
Register SuperHRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
return SH::R14;
+}
+
+Register SuperHRegisterInfo::getFrameRegister() const {
+ return SH::R14;
+}
+
+Register SuperHRegisterInfo::getStackRegister() const {
+ return SH::R15;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index c5c6dbb88e2af..c40cffab52e7a 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -33,12 +33,16 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
const uint32_t *getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const override;
const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const override;
BitVector getReservedRegs(const MachineFunction &MF) const override;
+ const TargetRegisterClass *getLargestLegalSuperClass(const TargetRegisterClass *RC,
+ const MachineFunction &MF) const override;
+ Register getFrameRegister(const MachineFunction &MF) const override;
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;
- Register getFrameRegister(const MachineFunction &MF) const override;
- const TargetRegisterClass *intRegClass(unsigned Size) const;
+ // Helpers
+ Register getFrameRegister() const;
+ Register getStackRegister() const;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index a1594fb811b08..f826f06f14337 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -151,13 +151,10 @@ let Namespace = "SH" in {
// Register Classes
//===----------------------------------------------------------------------===//
-def GPR : RegisterClass<"SH", [ i32 ], 32, (add
- R0, R1, R2, R3, R4, R5, R6, R7, // Banked memory
- R8, R9, R10, R11, R12, R13, R14, R15 // Non-banked memory.
-)>;
+def GPR : RegisterClass<"SH", [ i8, i16, i32 ], 32, (sequence "R%u", 0, 15)>;
// 32-bit floating point registers.
-def FR32 : RegisterClass<"SH", [f32], 32, (add
+def FR32 : RegisterClass<"SH", [ f32 ], 32, (add
// FR
FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7,
FR8, FR9, FR10, FR11, FR12, FR13, FR14, FR15,
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 27a5bf798a5a5..09befc32c7ead 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -39,6 +39,7 @@ class SuperHPassConfig : public TargetPassConfig {
: TargetPassConfig(TM, PM) {}
bool addInstSelector() override;
+ void addPreSched2() override;
SuperHTargetMachine &getSuperHTargetMachine() const {
return getTM<SuperHTargetMachine>();
}
@@ -48,6 +49,11 @@ bool SuperHPassConfig::addInstSelector() {
addPass(createSuperHISelDag(getSuperHTargetMachine(), getOptLevel()));
return false;
}
+
+void SuperHPassConfig::addPreSched2() {
+ addPass(createSuperHFillDelaySlotsPass());
+}
+
} // namespace
>From 755d0e46993773c77c729962b56161ddd644ba5e Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 10 Aug 2026 10:02:03 +0200
Subject: [PATCH 18/39] Move canFillDelaySlot to InstrInfo
---
.../Target/SuperH/SuperHFillDelaySlots.cpp | 9 ++----
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 30 -------------------
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 26 +++++++---------
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 6 +---
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 4 +--
5 files changed, 15 insertions(+), 60 deletions(-)
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index f96038e3b9cb7..76dc6ff0eed2b 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -44,7 +44,7 @@ class SuperHFillDelaySlots : public MachineFunctionPass {
typedef Block::iterator BlockIt;
const SuperHRegisterInfo *TRI;
- const TargetInstrInfo *TII;
+ const SuperHInstrInfo *TII;
bool hasDelaySlot(MachineInstr &I);
bool expandMBB(Block &MBB);
@@ -63,12 +63,7 @@ bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
// If the prior instruction does not have a delay slot
// we swap the instructions.
- //
- // NOTE: SuperH does not allow branch instructions
- // of any kind to be situated in a delay slot.
- // as such we fall through to the NOP in that
- // instance.
- if (!Prev->isBranch() && !Prev->hasDelaySlot()) {
+ if (TII->canFillDelaySlot(Prev->getOpcode())) {
LDBG() << "Swapping " << TII->getName(MI.getOpcode())
<< " and " << TII->getName(Prev->getOpcode())
<< " @ " << MBB.getParent()->getName();
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 5c5f851ec4a72..badd48f1df62a 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -96,34 +96,6 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValu
// Branch Lowering
//===----------------------------------------------------------------------===//
-// Due to delay slots there needs to be a bit more smarts
-// in here.
-bool SuperHDAGToDAGISel::trySelectRET(SDNode *N) {
- SDValue Chain = N->getOperand(0);
- unsigned LastOpNum = N->getNumOperands() - 1;
-
- // Skip the incoming flag if present
- if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
- --LastOpNum;
- }
-
- SDLoc DL(N);
- SmallVector<SDValue, 8> Ops;
-
- // RTS implicitly depends on the R0 register for
- // return values.
- Ops.push_back(CurDAG->getRegister(SH::R0, MVT::i32));
- Ops.push_back(Chain);
- Ops.push_back(Chain.getValue(1));
-
- SDNode *ResNode = CurDAG->getMachineNode(SH::RTS, DL, MVT::Other, Ops);
- //ResNode = CurDAG->getMachineNode(SH::NOP, DL, MVT::Other, SDValue(ResNode, 0));
-
- ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
- CurDAG->RemoveDeadNode(N);
- return true;
-}
-
bool SuperHDAGToDAGISel::trySelectFrameIndex(SDNode *N) {
auto DL = CurDAG->getDataLayout();
@@ -140,8 +112,6 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
switch(Opcode) {
case ISD::FrameIndex:
return trySelectFrameIndex(N);
- case SHISD::RET_GLUE:
- return trySelectRET(N);
default:
return false;
}
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 8489d91f8ac85..551e469a9b354 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -52,20 +52,14 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
llvm_unreachable("Impossible reg-to-reg copy");
}
-bool SuperHInstrInfo::expandRET(MachineInstr &MI) const {
- MachineBasicBlock &MBB = *MI.getParent();
- MachineBasicBlock::iterator MBBI = MI.getIterator();
- DebugLoc DL = MI.getDebugLoc();
-
-
- BuildMI(MBB, MBBI, DL, get(SH::NOP));
- return true;
-}
-
-bool SuperHInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
- switch(MI.getOpcode()) {
- case SH::RTS:
- return expandRET(MI);
- }
- return false;
+// Gets whether a given opcode can fill a delay slot.
+//
+// SuperH does not allow branch instructions of any kind to be situated
+// in a delay slot, nor does it allow instructions with delay slots
+// to be chained together.
+bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
+ auto Desc = this->get(Opcode);
+ return !Desc.hasDelaySlot() &&
+ !Desc.isBranch() &&
+ !Desc.isCall() && !Desc.isReturn();
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index bbd95d0148c89..78e9d10ae445c 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -41,11 +41,7 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
bool RenamableDest = false,
bool RenamableSrc = false) const override;
- bool expandPostRAPseudo(MachineInstr &MI) const override;
-
-private:
- // Custom expansions
- bool expandRET(MachineInstr &MI) const;
+ bool canFillDelaySlot(unsigned Opcode) const;
};
const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 32f27707ddf78..7ebddb4759fc9 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -916,7 +916,7 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
// Call Instructions
//===--------------------------------------------------------------------------===//
-let isCall = 1 in {
+let isCall = 1, hasDelaySlot = 1 in {
let Uses = [GBR] in
def JSRRmi : InstRm<0b0100000000001011,
(outs), (ins GPRMem:$Rm),
@@ -933,7 +933,7 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1 in {
def RTS : Inst<0b0000000000001011,
(outs), (ins),
"rts",
- []>;
+ [(SHRetGlue)]>;
}
>From bf738cede413a9396556c1c4416d3fea5dfb19af Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 10 Aug 2026 10:04:24 +0200
Subject: [PATCH 19/39] Fix comment
---
llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 76dc6ff0eed2b..9f7bacb1c92b5 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -61,8 +61,8 @@ bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
if (auto *Prev = MBBI->getPrevNode()) {
- // If the prior instruction does not have a delay slot
- // we swap the instructions.
+ // If the prior instruction is capable of filling the delay slot
+ // swap the 2 instructions.
if (TII->canFillDelaySlot(Prev->getOpcode())) {
LDBG() << "Swapping " << TII->getName(MI.getOpcode())
<< " and " << TII->getName(Prev->getOpcode())
>From 217effd83bbf130c67dc8a2d7a290eea40bf223c Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 10 Aug 2026 11:50:23 +0200
Subject: [PATCH 20/39] Add isDelayIllegal TSFlag
---
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 12 +++++++---
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 4 ++++
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 3 ++-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 24 +++++++++----------
4 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 5db9816b1ca2d..4d11c6e99983c 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -40,11 +40,15 @@ static unsigned getShiftAmt(uint32_t Val) {
}
// Helper to emit stack pointer adjustment.
-static void emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int32_t AdjValue) {
+static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int32_t AdjValue) {
DebugLoc dl;
const SuperHInstrInfo &TII = *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
const SuperHRegisterInfo &RII = *static_cast<const SuperHRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
MachineInstr::MIFlag MFlag = AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
+
+ // No stack frame allocation neccesary.
+ if (AdjValue == 0)
+ return false;
Register SP = RII.getStackRegister();
@@ -56,7 +60,7 @@ static void emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
.addImm((int)AdjValue)
.addReg(SP);
- return;
+ return true;
}
// Slow path, shift 8 bits at a time into r0.
@@ -93,6 +97,7 @@ static void emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
.addReg(SH::R0, RegState::Kill)
.addReg(SP)
.setMIFlag(MFlag);
+ return true;
}
void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
@@ -162,7 +167,8 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
.setMIFlag(MachineInstr::FrameDestroy);
// 3. Delete stack frame, restoring stack pointer.
- emitSPAdj(MF, MBB, MBBI, StackSize);
+ if (StackSize > 0)
+ emitSPAdj(MF, MBB, MBBI, StackSize);
}
MachineBasicBlock::iterator
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index df62cf6e9cfc4..1c2e6e03f6b3c 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -45,6 +45,10 @@ class SHInst<dag outs, dag ins, string asmstr, list<dag> pattern = []>
dag InOperandList = ins;
let AsmString = asmstr;
let Pattern = pattern;
+
+ // Whether the instruction is incompatible with delay slots.
+ bit isDelayIllegal = 0;
+ let TSFlags{0} = isDelayIllegal;
}
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 551e469a9b354..b5015c9e8dc63 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -61,5 +61,6 @@ bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
auto Desc = this->get(Opcode);
return !Desc.hasDelaySlot() &&
!Desc.isBranch() &&
- !Desc.isCall() && !Desc.isReturn();
+ !Desc.isCall() && !Desc.isReturn() &&
+ !(Desc.TSFlags & 0x1);
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 7ebddb4759fc9..3d7303b507dbd 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -229,21 +229,21 @@ def MOVI8Rn : InstRnI8<0b1110000000000000,
[(set i32:$Rn, imm8:$imm)]>;
// mov @(disp, PC), R0
-let hasSideEffects = 0, mayLoad = 1, Defs = [R0] in
+let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
def MOVAD8PCR0 : InstD8<0b1100011100000000,
(outs), (ins disp8:$disp),
"mov @($disp,PC),R0",
[]>;
// mov.w @(disp,PC), Rn
-let hasSideEffects = 0, mayLoad = 1 in
+let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
def MOVWD8PCRn : InstRnD8<0b1001000000000000,
(outs GPR:$Rn), (ins disp8:$disp),
"mov.w @($disp,PC),$Rn",
[(set i32:$Rn, (sextloadi16 addr:$disp))]>;
// mov.l @(disp,PC), Rn
-let hasSideEffects = 0, mayLoad = 1 in
+let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
def MOVLD8PCRn : InstRnD8<0b1101000000000000,
(outs GPR:$Rn), (ins disp8:$disp),
"mov.l @($disp,PC),$Rn",
@@ -954,14 +954,14 @@ let Defs = [SR] in
def CLRT : Inst<0b0000000000001000, (outs), (ins), "clrt", []>;
// ldc Rm, SR
-let Defs = [SR] in
+let Defs = [SR], isDelayIllegal = 1 in
def LDCRmSR : InstRm<0b0100000000001110,
(outs), (ins GPR:$Rm),
"ldc $Rm,SR",
[]>;
// ldc.l @Rm+, SR
-let Defs = [SR] in
+let Defs = [SR], isDelayIllegal = 1 in
def LDCLRminciSR : InstRm<0b0100000000000111,
(outs), (ins GPR:$Rm),
"ldc.l @$Rm+,SR",
@@ -982,14 +982,14 @@ def LDCLRminciGBR : InstRm<0b0100000000010111,
[]>;
// ldc Rm, VBR
-let Defs = [VBR] in
+let Defs = [VBR], isDelayIllegal = 1 in
def LDCRmVBR : InstRm<0b0100000000101110,
(outs), (ins GPR:$Rm),
"ldc $Rm,VBR",
[]>;
// ldc.l @Rm+, VBR
-let Defs = [VBR] in
+let Defs = [VBR], isDelayIllegal = 1 in
def LDCLRminciVBR : InstRm<0b0100000000100111,
(outs), (ins GPR:$Rm),
"ldc.l @$Rm+,VBR",
@@ -1050,18 +1050,18 @@ let Defs = [SR] in
def SETT : Inst<0b0000000000011000, (outs), (ins), "sett", []>;
// sleep
-let hasSideEffects = 1 in
+let hasSideEffects = 1, isDelayIllegal = 1 in
def SLEEP : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
// stc SR,Rn
-let Uses = [SR] in
+let Uses = [SR], isDelayIllegal = 1 in
def STCSRRn : InstRn<0b0000000000000010,
(outs GPR:$Rn), (ins),
"stc SR,$Rn",
[]>;
// stc.l SR, at -Rn
-let Uses = [SR] in
+let Uses = [SR], isDelayIllegal = 1 in
def STCLSRRndeci : InstRn<0b0100000000000011,
(outs GPR:$Rn), (ins),
"stc.l SR, at -$Rn",
@@ -1082,14 +1082,14 @@ def STCLGBRRndeci : InstRn<0b0100000000010011,
[]>;
// stc VBR,Rn
-let Uses = [VBR] in
+let Uses = [VBR], isDelayIllegal = 1 in
def STCVBRRn : InstRn<0b0000000000100010,
(outs GPR:$Rn), (ins),
"stc VBR,$Rn",
[]>;
// stc.l VBR, at -Rn
-let Uses = [VBR] in
+let Uses = [VBR], isDelayIllegal = 1 in
def STCLVBRRndeci : InstRn<0b0100000000100011,
(outs GPR:$Rn), (ins),
"stc.l VBR, at -$Rn",
>From 58b354279be62f93330f8867af8d1a15be792243 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 21 Aug 2026 22:47:56 +0200
Subject: [PATCH 21/39] Further SuperH instruction lowering
---
clang/include/clang/Options/Options.td | 19 +
.../llvm/BinaryFormat/ELFRelocs/SuperH.def | 2 +-
llvm/lib/Target/SuperH/CMakeLists.txt | 10 +-
.../SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 12 +-
.../SuperH/MCTargetDesc/SuperHBaseInfo.h | 143 ++
.../MCTargetDesc/SuperHELFObjectWriter.cpp | 129 +-
.../SuperH/MCTargetDesc/SuperHFixupKinds.h | 2 +-
.../SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 55 +-
.../SuperH/MCTargetDesc/SuperHInstPrinter.h | 2 +
.../SuperH/MCTargetDesc/SuperHMCAsmInfo.h | 17 +-
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 42 +-
.../MCTargetDesc/SuperHTargetStreamer.cpp | 3 +-
llvm/lib/Target/SuperH/SuperH.h | 2 +
llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp | 198 ++-
.../Target/SuperH/SuperHBasicBlockInfo.cpp | 110 ++
llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h | 157 +++
.../SuperH/SuperHConstantIslandPass.cpp | 1184 +++++++++++++++++
.../Target/SuperH/SuperHConstantPoolValue.cpp | 223 ++++
.../Target/SuperH/SuperHConstantPoolValue.h | 212 +++
.../Target/SuperH/SuperHFillDelaySlots.cpp | 80 +-
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 170 ++-
llvm/lib/Target/SuperH/SuperHFrameLowering.h | 9 +-
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 239 +++-
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 226 +++-
llvm/lib/Target/SuperH/SuperHISelLowering.h | 40 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 201 ++-
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 42 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 301 +++--
llvm/lib/Target/SuperH/SuperHMCInstLower.cpp | 34 +-
.../SuperH/SuperHMachineFunctionInfo.cpp | 126 ++
.../Target/SuperH/SuperHMachineFunctionInfo.h | 68 +
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 10 +-
llvm/lib/Target/SuperH/SuperHRegisterInfo.h | 1 +
llvm/lib/Target/SuperH/SuperHSubtarget.cpp | 116 +-
llvm/lib/Target/SuperH/SuperHSubtarget.h | 51 +-
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 31 +
llvm/lib/Target/SuperH/SuperHTargetMachine.h | 4 +
37 files changed, 3959 insertions(+), 312 deletions(-)
create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHBaseInfo.h
create mode 100644 llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
create mode 100644 llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
create mode 100644 llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
create mode 100644 llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 6fc8806ba683c..27e67a48523af 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -218,6 +218,8 @@ def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
Group<m_Group>, DocName<"Hexagon">;
def m_sparc_Features_Group : OptionGroup<"<sparc features group>">,
Group<m_Group>, DocName<"SPARC">;
+def m_superh_Features_Group : OptionGroup<"<superh features group>">,
+ Group<m_Group>, DocName<"SuperH">;
// The features added by this group will not be added to target features.
// These are explicitly handled.
def m_hexagon_Features_HVX_Group : OptionGroup<"<hexagon features group>">,
@@ -7047,6 +7049,23 @@ foreach i = 0 ... 5 in
HelpText<"Reserve the I"#i#" register (SPARC only)">;
} // let Flags = [TargetSpecific]
+// SuperH feature flags
+let Flags = [TargetSpecific] in {
+ def maccumulate_outgoing_args : Flag<["-"], "maccumulate-outgoing-args">,
+ Group<m_superh_Features_Group>,
+ HelpText<"Reserve space for outgoing arguments in the function prologue. (SuperH only)">;
+ def mcbranch_force_delay_slot : Flag<["-"], "mcbranch-force-delay-slot">,
+ Group<m_superh_Features_Group>,
+ HelpText<"Force the usage of delay slots for conditional branches. (SuperH only)">;
+ def mfsca : Flag<["-"], "mfsca">, Group<m_superh_Features_Group>,
+ HelpText<"Enable the use of the fsca instruction. (SuperH only)">;
+ def mfsrra : Flag<["-"], "mfsrra">, Group<m_superh_Features_Group>,
+ HelpText<"Enable the use of the fsrra instruction. (SuperH only)">;
+ def mzdcbranch : Flag<["-"], "mzdcbranch">,
+ Group<m_superh_Features_Group>,
+ HelpText<"Assume that zero displacement conditional branches are fast. (SuperH only)">;
+} // let Flags = [TargetSpecific]
+
// M68k features flags
let Flags = [TargetSpecific] in {
def m68000 : Flag<["-"], "m68000">, Group<m_m68k_Features_Group>;
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
index 943ae7dd39440..2db8a2d5c4938 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
@@ -30,7 +30,7 @@ ELF_RELOC(R_SH_GOTPLT10BY4, 189)
ELF_RELOC(R_SH_GOTPLT10BY8, 191)
ELF_RELOC(R_SH_GOTOFF, 166)
ELF_RELOC(R_SH_GOTOFF_LOW16, 181)
-ELF_RELOC(R_SH_GOTOFF_MEWLOW16, 182)
+ELF_RELOC(R_SH_GOTOFF_MEDLOW16, 182)
ELF_RELOC(R_SH_GOTOFF_MEDHI16, 183)
ELF_RELOC(R_SH_GOTOFF_HI16, 184)
ELF_RELOC(R_SH_GOTPC, 167)
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index a67293ce502f4..a09955850e10a 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -19,15 +19,19 @@ add_public_tablegen_target(SuperHCommonTableGen)
add_llvm_target(SuperHCodeGen
SuperHTargetMachine.cpp
SuperHFrameLowering.cpp
+ SuperHConstantPoolValue.cpp
+ SuperHBasicBlockInfo.cpp
+ SuperHMachineFunctionInfo.cpp
SuperHRegisterInfo.cpp
- SuperHMCInstLower.cpp
+ SuperHInstrInfo.cpp
SuperHSelectionDAGInfo.cpp
- SuperHISelDAGToDAG.cpp
SuperHISelLowering.cpp
+ SuperHISelDAGToDAG.cpp
+ SuperHMCInstLower.cpp
SuperHAsmPrinter.cpp
- SuperHInstrInfo.cpp
SuperHSubtarget.cpp
SuperHFillDelaySlots.cpp
+ SuperHConstantIslandPass.cpp
LINK_COMPONENTS
Analysis
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 26bfcbbca5b03..ae24d50d921b8 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -41,14 +41,14 @@ SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) :
bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
const MCSubtargetInfo *STI) const {
- const uint16_t SH_NopEnc = 0b0000000000001001;
+ const uint16_t SHNopEnc = 0b0000000000001001;
// If the count is not 4-byte aligned, we must be writing data into the
// text section (otherwise we have unaligned instructions, and thus have
// far bigger problems), so just write NOP instructions.
uint64_t NumNops = Count / 2;
for (uint64_t i = 0; i != NumNops; ++i)
- support::endian::write(OS, SH_NopEnc, Endian);
+ support::endian::write(OS, SHNopEnc, Endian);
// Write any straggling zeros needed.
OS.write_zeros(Count & 1);
@@ -70,7 +70,7 @@ std::optional<MCFixupKind> SuperHAsmBackend::getFixupKind(StringRef Name) const
MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
// clang-format off
- const static MCFixupKindInfo Infos[SuperH::NumTargetFixupKinds] = {
+ const static MCFixupKindInfo Infos[SH::NumTargetFixupKinds] = {
// This table *must* be in same the order of fixup_* kinds in
// SuperHFixupKinds.h.
//
@@ -123,7 +123,7 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
if (Kind < FirstTargetFixupKind)
return MCAsmBackend::getFixupKindInfo(Kind);
- assert(unsigned(Kind - FirstTargetFixupKind) < SuperH::NumTargetFixupKinds &&
+ assert(unsigned(Kind - FirstTargetFixupKind) < SH::NumTargetFixupKinds &&
"Invalid kind!");
return Infos[Kind - FirstTargetFixupKind];
@@ -171,8 +171,10 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
default:
return {};
+ case FK_Data_1:
case FK_Data_2:
- case FK_Data_4: {
+ case FK_Data_4:
+ case FK_Data_8: {
const auto *EValue = Fixup.getValue();
if (!EValue->evaluateAsRelocatable(PCITarget, Asm))
return true;
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHBaseInfo.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHBaseInfo.h
new file mode 100644
index 0000000000000..f0f7b7e51c847
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHBaseInfo.h
@@ -0,0 +1,143 @@
+//===-- SuperHBaseInfo.h - Top level definitions for SH MC --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===------------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains small standalone helper functions and enum definitions
+/// for the SuperH 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 LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHBASEINFO_H
+#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHBASEINFO_H
+
+#include "SuperHMCTargetDesc.h"
+
+#include "llvm/MC/MCExpr.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#define GET_INSTRINFO_MI_OPS_INFO
+#define GET_INSTRINFO_OPERAND_TYPES_ENUM
+#define GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP
+#include "SuperHGenInstrInfo.inc"
+
+namespace llvm {
+
+namespace SHII {
+/// Target Operand Flag enum.
+enum TOF {
+
+ MO_NO_FLAG,
+
+ /// On a symbol operand this indicates that the immediate is the absolute
+ /// address of the symbol.
+ MO_DIR,
+
+ /// On a symbol operand this indicates that the immediate is the pc-relative
+ /// address of the symbol.
+ MO_PCREL,
+
+ /// On a symbol operand this indicates that the immediate is the offset to
+ /// the GOT entry for the symbol name from the base of the GOT.
+ ///
+ /// name at GOT
+ MO_GOT,
+
+ /// On a symbol operand this indicates that the immediate is the offset to
+ /// the location of the symbol name from the base of the GOT.
+ ///
+ /// name at GOTOFF
+ MO_GOTOFF,
+
+ /// On a symbol operand this indicates that the immediate is offset to the
+ /// PLT entry of symbol name from the current code location.
+ ///
+ /// name at PLT
+ MO_PLT,
+
+ /// On a symbol operand this indicates that the immediate is offset to the
+ /// location of the symbol name from the base of the GOT added to the storage
+ /// unit.
+ ///
+ /// name at GOTPLT
+ MO_GOTPLT,
+
+ /// On a symbol operand this indicates that the immediate is offset to the
+ /// GOT entry for the symbol name from the current code location.
+ ///
+ /// name at GOTPC
+ MO_GOTPC,
+
+}; // enum TOF
+
+/// Return true if the specified TargetFlag operand is a reference to a stub
+/// for a global, not the global itself.
+inline static bool isGlobalStubReference(unsigned char TargetFlag) {
+ switch (TargetFlag) {
+ default:
+ return false;
+ case SHII::MO_GOTPC: // pc-relative GOT reference.
+ case SHII::MO_GOT: // normal GOT reference.
+ return true;
+ }
+}
+
+/// Return True if the specified GlobalValue is a direct reference for a
+/// symbol.
+inline static bool isDirectGlobalReference(unsigned char Flag) {
+ switch (Flag) {
+ default:
+ return false;
+ case SHII::MO_NO_FLAG:
+ case SHII::MO_DIR:
+ case SHII::MO_PCREL:
+ return true;
+ }
+}
+
+/// Return true if the specified global value reference is relative to a 32-bit
+/// PIC base (M68kISD::GLOBAL_BASE_REG). If this is true, the addressing mode
+/// has the PIC base register added in.
+inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
+ switch (TargetFlag) {
+ default:
+ return false;
+ case SHII::MO_GOTOFF: // isPICStyleGOT: local global.
+ case SHII::MO_GOT: // isPICStyleGOT: other global.
+ return true;
+ }
+}
+
+/// Return True if the specified GlobalValue requires PC addressing mode.
+inline static bool isPCRelGlobalReference(unsigned char Flag) {
+ switch (Flag) {
+ default:
+ return false;
+ case SHII::MO_GOTPC:
+ case SHII::MO_PCREL:
+ return true;
+ }
+}
+
+/// Return True if the Block is referenced using PC
+inline static bool isPCRelBlockReference(unsigned char Flag) {
+ switch (Flag) {
+ default:
+ return false;
+ case SHII::MO_PCREL:
+ return true;
+ }
+}
+
+} // namespace SHII
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index 0e337f12d546a..20c6718e399ce 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -7,6 +7,9 @@
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
+#include "MCTargetDesc/SuperHFixupKinds.h"
+#include "SuperHMCAsmInfo.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFObjectWriter.h"
@@ -19,6 +22,8 @@
using namespace llvm;
+#define DEBUG_TYPE "sh-elf-objwriter"
+
namespace llvm {
class SuperHELFObjectWriter : public MCELFObjectTargetWriter {
public:
@@ -41,12 +46,128 @@ namespace llvm {
unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
const MCValue &Target,
bool IsPCRel) const {
- auto Kind = Fixup.getKind();
- uint8_t Specifier = Target.getSpecifier();
- if (Kind == FK_Data_4 || Kind == FK_Data_2)
+ auto Spec = Target.getSpecifier();
+ switch ((unsigned)Fixup.getKind()) {
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ case FK_Data_8:
return ELF::R_SH_NONE;
- return Specifier;
+ case SH::fixup_got32:
+ return ELF::R_SH_GOT32;
+
+ case SH::fixup_got_low16:
+ return ELF::R_SH_GOT_LOW16;
+
+ case SH::fixup_got_medlow16:
+ return ELF::R_SH_GOT_MEDLOW16;
+
+ case SH::fixup_got_medhi16:
+ return ELF::R_SH_GOT_MEDHI16;;
+
+ case SH::fixup_got_hi16:
+ return ELF::R_SH_GOT_HI16;
+
+ case SH::fixup_plt32:
+ return ELF::R_SH_PLT32;
+
+ case SH::fixup_plt_low16:
+ return ELF::R_SH_PLT_LOW16;
+
+ case SH::fixup_plt_medlow16:
+ return ELF::R_SH_PLT_MEDLOW16;
+
+ case SH::fixup_plt_medhi16:
+ return ELF::R_SH_PLT_MEDHI16;;
+
+ case SH::fixup_plt_hi16:
+ return ELF::R_SH_PLT_HI16;
+
+ case SH::fixup_gotplt32:
+ return ELF::R_SH_GOTPLT32;
+
+ case SH::fixup_gotplt_low16:
+ return ELF::R_SH_GOTPLT_LOW16;
+
+ case SH::fixup_gotplt_medlow16:
+ return ELF::R_SH_GOTPLT_MEDLOW16;
+
+ case SH::fixup_gotplt_medhi16:
+ return ELF::R_SH_GOTPLT_MEDHI16;;
+
+ case SH::fixup_gotplt_hi16:
+ return ELF::R_SH_GOTPLT_HI16;
+
+ case SH::fixup_gotoff:
+ return ELF::R_SH_GOTOFF;
+
+ case SH::fixup_gotoff_low16:
+ return ELF::R_SH_GOTOFF_LOW16;
+
+ case SH::fixup_gotoff_medlow16:
+ return ELF::R_SH_GOTOFF_MEDLOW16;
+
+ case SH::fixup_gotoff_medhi16:
+ return ELF::R_SH_GOTOFF_MEDHI16;;
+
+ case SH::fixup_gotoff_hi16:
+ return ELF::R_SH_GOTOFF_HI16;
+
+ case SH::fixup_gotpc:
+ return ELF::R_SH_GOTPC;
+
+ case SH::fixup_gotpc_low16:
+ return ELF::R_SH_GOTPC_LOW16;
+
+ case SH::fixup_gotpc_medlow16:
+ return ELF::R_SH_GOTPC_MEDLOW16;
+
+ case SH::fixup_gotpc_medhi16:
+ return ELF::R_SH_GOTPC_MEDHI16;;
+
+ case SH::fixup_gotpc_hi16:
+ return ELF::R_SH_GOTPC_HI16;
+
+ case SH::fixup_copy:
+ return ELF::R_SH_COPY;
+
+ case SH::fixup_copy64:
+ return ELF::R_SH_COPY64;
+
+ case SH::fixup_glob_dat:
+ return ELF::R_SH_GLOB_DAT;
+
+ case SH::fixup_glob_dat64:
+ return ELF::R_SH_GLOB_DAT64;
+
+ case SH::fixup_jump_slot:
+ return ELF::R_SH_JMP_SLOT;
+
+ case SH::fixup_jump_slot64:
+ return ELF::R_SH_JMP_SLOT64;
+
+ case SH::fixup_relative:
+ return ELF::R_SH_RELATIVE;
+
+ case SH::fixup_relative64:
+ return ELF::R_SH_RELATIVE64;
+
+ case SH::fixup_dir32:
+ return ELF::R_SH_DIR32;
+
+ case SH::fixup_rel32:
+ return ELF::R_SH_REL32;
+
+ case SH::fixup_64:
+ return ELF::R_SH_64;
+
+ case SH::fixup_64_pcrel:
+ return ELF::R_SH_64_PCREL;
+
+ default:
+ llvm_unreachable("invalid fixup kind!");
+ }
}
bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
index ee8865c44bb26..821a588c3dd44 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
@@ -12,7 +12,7 @@
#include "llvm/MC/MCFixup.h"
namespace llvm {
-namespace SuperH {
+namespace SH {
// clang-format off
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 987b0594cf813..fadac2158f630 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -25,9 +25,9 @@ using namespace llvm;
// The generated AsmMatcher SparcGenAsmWriter uses "SuperH" as the target
// namespace. But SuperH backend uses "SH" as its namespace.
namespace llvm {
- namespace SuperH {
- using namespace SH;
- }
+ namespace SuperH {
+ using namespace SH;
+ }
}
#define GET_INSTRUCTION_NAME
@@ -38,33 +38,42 @@ SuperHInstPrinter::SuperHInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MI
const MCRegisterInfo &MRI) : MCInstPrinter(MAI, MII, MRI) {}
void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
- OS << StringRef(getRegisterName(Reg)).lower();
+ OS << StringRef(getRegisterName(Reg)).lower();
+}
+
+void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address,
+ unsigned OpNo, raw_ostream &O) {
+ printOperand(MI, OpNo, O);
+}
+
+void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
+ printOperand(MI, OpNo, O);
}
void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
- const MCOperand &Op = MI->getOperand(OpNo);
-
- // Print Register
- if (Op.isReg()) {
- printRegName(O, Op.getReg());
- return;
- }
+ const MCOperand &Op = MI->getOperand(OpNo);
+
+
+ // Print Register
+ if (Op.isReg()) {
+ printRegName(O, Op.getReg());
+ return;
+ }
- // Print immediates
- if (Op.isImm()) {
- O << Op.getImm();
- return;
- }
+ // Print immediates
+ if (Op.isImm()) {
+ O << Op.getImm();
+ return;
+ }
- // Print symbol references
- if (Op.isBareSymbolRef()) {
- const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
- O << SymOp->getSymbol().getName();
- return;
- }
+ // Print symbol references
+ if (const MCSymbolRefExpr *SymOp = dyn_cast_or_null<MCSymbolRefExpr>(Op.getExpr())) {
+ O << SymOp->getSymbol().getName();
+ return;
+ }
}
void SuperHInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &OS) {
- printInstruction(MI, Address, OS);
+ printInstruction(MI, Address, OS);
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index ebdaca0d64915..f22b48ac733b8 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -47,6 +47,8 @@ class SuperHInstPrinter : public MCInstPrinter {
private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
};
} // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
index 25cd78f53becc..0dfc47b66f766 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
@@ -16,6 +16,7 @@
#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCASMINFO_H
#include "llvm/MC/MCAsmInfoELF.h"
+#include "llvm/MC/MCExpr.h"
namespace llvm {
class Triple;
@@ -34,6 +35,20 @@ class SuperHMCAsmInfo : public MCAsmInfoELF {
const MCTargetOptions &Options);
};
-} // end namespace llvm
+namespace SH {
+using Specifier = uint16_t;
+enum {
+ S_None,
+
+ S_SH_NONE = MCSymbolRefExpr::FirstTargetSpecifier,
+ S_GOT,
+ S_GOT_OFF,
+ S_GOT_PCREL,
+ S_PCREL,
+ S_DIR,
+};
+} // namespace SH
+
+} // namespace llvm
#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 3f5d826bd1b13..55383441344a5 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -11,11 +11,14 @@
//===----------------------------------------------------------------------===//
+#include "SuperHFixupKinds.h"
+#include "SuperHMCAsmInfo.h"
#include "SuperHMCTargetDesc.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/bit.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
@@ -67,9 +70,17 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ unsigned getBranchTargetOpValue(const MCInst &MI, const MCExpr *Expr,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+
+ unsigned getOpBits(const MCInst &MI,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
};
} // end namespace
@@ -94,12 +105,25 @@ static bool isOpcode32(uint32_t Opcode) {
return Opcode > 0xFFFF;
}
+// Helper that gets the bits for the given instruction.
+unsigned SuperHMCCodeEmitter::getOpBits(const MCInst &MI,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ MCInst Inst = MCInst();
+ Inst.setOpcode(MI.getOpcode());
+ for(unsigned i = 0; i < MI.getNumOperands(); i++) {
+ Inst.addOperand(MCOperand::createImm(0));
+ }
+
+ return getBinaryCodeForInstr(Inst, Fixups, STI);
+}
+
void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
- uint32_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
+ uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
// NOTE: All base instructions are 16-bit in SH ASM
// But some instructions may be 32-bit for eg. SH2A or the DSP extensions.
@@ -117,9 +141,19 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
++MCNumEmitted;
}
+unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI,
+ const MCExpr *Expr,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ return getExprOpValue(MI, Expr, Fixups, STI);
+}
+
unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
+ if (!Expr)
+ return 0;
+
MCExpr::ExprKind Kind = Expr->getKind();
// Binary Op
@@ -128,12 +162,11 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
Kind = Expr->getKind();
}
- // Symbol Reference
if (Kind == MCExpr::SymbolRef) {
// NOTE: A few (DSP and SH2A) instructions are 32-bits wide.
// We handle those quite crudely.
- uint32_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
+ uint32_t OpCode = getOpBits(MI, Fixups, STI);
Fixups.push_back(MCFixup::create(0, Expr, isOpcode32(OpCode) ? FK_Data_4 : FK_Data_2, true));
return 0;
}
@@ -146,7 +179,8 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
return 0;
}
-unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI,
+ const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
if (MO.isReg())
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
index cd8db84311001..86e98b93b96a5 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
@@ -28,10 +28,9 @@ SuperHTargetELFStreamer::SuperHTargetELFStreamer(MCStreamer &S,
: SuperHTargetStreamer(S) {
ELFObjectWriter &W = getStreamer().getWriter();
unsigned EFlags = W.getELFHeaderEFlags();
-
W.setELFHeaderEFlags(EFlags);
}
MCELFStreamer &SuperHTargetELFStreamer::getStreamer() {
return static_cast<MCELFStreamer &>(Streamer);
-}
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index c0d62f8fb03f8..911234e3efefc 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -27,11 +27,13 @@ class SuperHTargetMachine;
FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel);
FunctionPass *createSuperHFillDelaySlotsPass();
+FunctionPass *createSuperHConstantIslandPass();
void initializeSuperHDAGToDAGISelLegacyPass(PassRegistry &);
void initializeSuperHAsmPrinterPass(PassRegistry &);
void initializeSuperHAsmPrinterPass(PassRegistry &);
void initializeSuperHFillDelaySlotsPass(PassRegistry &);
+void initializeSuperHConstantIslandsPass(PassRegistry &);
} // namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index c62e23430d2b5..884266d52eff9 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -11,16 +11,20 @@
//
//===-----------------------------------------------------------------------===//
+#include "MCTargetDesc/SuperHBaseInfo.h"
#include "MCTargetDesc/SuperHInstPrinter.h"
#include "MCTargetDesc/SuperHMCAsmInfo.h"
#include "MCTargetDesc/SuperHMCTargetDesc.h"
#include "MCTargetDesc/SuperHTargetStreamer.h"
#include "SuperH.h"
+#include "SuperHConstantPoolValue.h"
#include "SuperHMCInstLower.h"
#include "TargetInfo/SuperHTargetInfo.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Casting.h"
using namespace llvm;
@@ -29,6 +33,19 @@ using namespace llvm;
namespace {
class SuperHAsmPrinter : public AsmPrinter {
+public:
+ static char ID;
+
+private:
+
+ /// MCP - Keep a pointer to constantpool entries of the current
+ /// MachineFunction.
+ const MachineConstantPool *MCP;
+
+ /// InConstantPool - Maintain state when emitting a sequence of constant
+ /// pool entries so we can properly mark them as data regions.
+ bool InConstantPool = false;
+
SuperHTargetStreamer &getTargetStreamer() {
return static_cast<SuperHTargetStreamer &>(
*OutStreamer->getTargetStreamer());
@@ -37,16 +54,22 @@ class SuperHAsmPrinter : public AsmPrinter {
public:
explicit SuperHAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
- : AsmPrinter(TM, std::move(Streamer), ID) {}
+ : AsmPrinter(TM, std::move(Streamer), ID), MCP(nullptr) {}
StringRef getPassName() const override { return "SuperH Assembly Printer"; }
+ bool runOnMachineFunction(MachineFunction &F) override;
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
void emitFunctionBodyStart() override;
+ void emitFunctionBodyEnd() override;
void emitInstruction(const MachineInstr *MI) override;
+ // We emit them ourselves.
+ void emitConstantPool() override { }
+ void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
+
static const char *getRegisterName(MCRegister Reg) {
return SuperHInstPrinter::getRegisterName(Reg);
}
@@ -55,23 +78,63 @@ class SuperHAsmPrinter : public AsmPrinter {
const char *ExtraCode, raw_ostream &O) override;
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode, raw_ostream &O) override;
-
- static char ID;
};
} // namespace
+bool SuperHAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+ MCP = MF.getConstantPool();
+ return AsmPrinter::runOnMachineFunction(MF);
+}
-void SuperHAsmPrinter::emitFunctionBodyStart() {
- AsmPrinter::emitFunctionBodyStart();
+
+
+
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+// Convert a SuperH-specific constant pool modifier into the associated
+// specifier.
+static uint8_t getSpecifierFromModifier(SHCP::SHCPModifier Modifier) {
+ switch (Modifier) {
+ case SHCP::SHCPModifier::DIR:
+ case SHCP::SHCPModifier::no_modifier:
+ return SHII::MO_DIR;
+ default:
+ return SHII::MO_DIR;
+ }
}
-void SuperHAsmPrinter::emitInstruction(const MachineInstr *MI) {
- SuperHMCInstLower MCInstLowering(OutContext, *this);
- MCInst I;
- MCInstLowering.lowerInstruction(*MI, I);
- EmitToStreamer(*OutStreamer, I);
+
+
+//===----------------------------------------------------------------------===//
+// Operands
+//===----------------------------------------------------------------------===//
+
+void SuperHAsmPrinter::printOperand(const MachineInstr *MI, int OpNo, raw_ostream &O) {
+ const MachineOperand &MO = MI->getOperand(OpNo);
+
+ switch (MO.getType()) {
+ case MachineOperand::MO_Register:
+ O << StringRef(getRegisterName(MO.getReg())).lower();
+ break;
+ case MachineOperand::MO_Immediate:
+ O << MO.getImm();
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ O << getSymbol(MO.getGlobal());
+ break;
+ case MachineOperand::MO_ExternalSymbol:
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
+ break;
+ case MachineOperand::MO_MachineBasicBlock:
+ O << *MO.getMBB()->getSymbol();
+ break;
+ default:
+ llvm_unreachable("Not implemented yet!");
+ }
}
bool SuperHAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -79,13 +142,124 @@ bool SuperHAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
return false;
+ const MachineOperand &MO = MI->getOperand(OpNo);
+ if (MO.getType() == MachineOperand::MO_GlobalAddress)
+ PrintSymbolOperand(MO, O); // Print global symbols.
+ else
+ printOperand(MI, OpNo, O); // Fallback to ordinary cases.
- return false;
+ return false;
}
bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode, raw_ostream &O) {
- return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, O);
+ if (ExtraCode && ExtraCode[0])
+ return true; // Unknown modifier
+
+ const MachineOperand &MO = MI->getOperand(OpNo);
+
+ // Print direct memory operands.
+ if (MO.isGlobal() || MO.isSymbol() || MO.isMCSymbol()) {
+ PrintSymbolOperand(MO, O);
+ return false;
+ }
+ return false;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Constant Pool
+//===----------------------------------------------------------------------===//
+
+
+void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
+ const DataLayout &DL = getDataLayout();
+ int Size = DL.getTypeAllocSize(MCPV->getType());
+
+ MCSymbol *MCSym;
+ SuperHConstantPoolValue *SCPV = static_cast<SuperHConstantPoolValue*>(MCPV);
+ if (SCPV->isBlockAddress()) {
+ const BlockAddress *BA =
+ cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
+ MCSym = GetBlockAddressSymbol(BA);
+ } else if (SCPV->isGlobalValue()) {
+ const GlobalValue *GV = cast<SuperHConstantPoolConstant>(SCPV)->getGV();
+ MCSym = getSymbolPreferLocal(*GV);
+ } else {
+ assert(SCPV->isExtSymbol() && "unrecognized constant pool value");
+ auto Sym = cast<SuperHConstantPoolSymbol>(SCPV)->getSymbol();
+ MCSym = GetExternalSymbolSymbol(Sym);
+ }
+
+ // Create an MCSymbol for the reference.
+ const MCExpr *Expr = MCSymbolRefExpr::create(
+ MCSym,
+ OutContext
+ );
+ OutStreamer->emitValue(Expr, Size);
+}
+
+void SuperHAsmPrinter::emitFunctionBodyStart() {
+ AsmPrinter::emitFunctionBodyStart();
+}
+
+void SuperHAsmPrinter::emitFunctionBodyEnd() {
+
+ // Make sure to terminate any constant pools that were at the end
+ // of the function.
+ if (!InConstantPool)
+ return;
+
+ InConstantPool = false;
+ OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
+}
+
+
+void SuperHAsmPrinter::emitInstruction(const MachineInstr *MI) {
+ const SuperHSubtarget &STI = MF->getSubtarget<SuperHSubtarget>();
+ const DataLayout &DL = getDataLayout();
+ MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
+ SuperHTargetStreamer &STS = static_cast<SuperHTargetStreamer &>(TS);
+
+ // If we just ended a constant pool, mark it as such.
+ if (InConstantPool && MI->getOpcode() != SH::CONSTPOOL_ENTRY) {
+ OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
+ InConstantPool = false;
+ }
+
+ unsigned Opc = MI->getOpcode();
+ switch (Opc) {
+ default: {
+ SuperHMCInstLower MCInstLowering(OutContext, *this);
+
+ MCInst I;
+ MCInstLowering.lowerInstruction(*MI, I);
+ EmitToStreamer(*OutStreamer, I);
+ return;
+ }
+
+ case SH::CONSTPOOL_ENTRY: {
+ unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
+ unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
+
+ // If this is the first entry of the pool, mark it.
+ if (!InConstantPool) {
+ OutStreamer->emitDataRegion(MCDR_DataRegion);
+ InConstantPool = true;
+ }
+
+ OutStreamer->emitLabel(GetCPISymbol(LabelId));
+
+ const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
+ if (MCPE.isMachineConstantPoolEntry())
+ emitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
+ else
+ emitGlobalConstant(DL, MCPE.Val.ConstVal);
+ return;
+ }
+ }
}
char SuperHAsmPrinter::ID = 0;
diff --git a/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
new file mode 100644
index 0000000000000..3a139ba14acf0
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
@@ -0,0 +1,110 @@
+//===-- SuperHBasicBlockInfo.cpp - Basic Block Information ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHBasicBlockInfo.h"
+
+#define DEBUG_TYPE "sh-bb-utils"
+
+using namespace llvm;
+
+namespace llvm {
+
+void SuperHBasicBlockUtils::computeBlockSize(MachineBasicBlock *MBB) {
+ LLVM_DEBUG(dbgs() << "computeBlockSize: " << MBB->getName() << "\n");
+ BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];
+ BBI.Size = 0;
+ BBI.Unalign = 0;
+ BBI.PostAlign = Align(1);
+
+ for (MachineInstr &I : *MBB) {
+ BBI.Size += TII->getInstSizeInBytes(I);
+ // For inline asm, getInstSizeInBytes returns a conservative estimate.
+ // The actual size may be smaller, but still a multiple of the instr size.
+ if (I.isInlineAsm())
+ BBI.Unalign = 2;
+ }
+}
+
+/// getOffsetOf - Return the current offset of the specified machine instruction
+/// from the start of the function. This offset changes as stuff is moved
+/// around inside the function.
+unsigned SuperHBasicBlockUtils::getOffsetOf(MachineInstr *MI) const {
+ const MachineBasicBlock *MBB = MI->getParent();
+
+ // The offset is composed of two things: the sum of the sizes of all MBB's
+ // before this instruction's block, and the offset from the start of the block
+ // it is in.
+ unsigned Offset = BBInfo[MBB->getNumber()].Offset;
+
+ // Sum instructions before MI in MBB.
+ for (MachineBasicBlock::const_iterator I = MBB->begin(); &*I != MI; ++I) {
+ assert(I != MBB->end() && "Didn't find MI in its own basic block?");
+ Offset += TII->getInstSizeInBytes(*I);
+ }
+ return Offset;
+}
+
+/// isBBInRange - Returns true if the distance between specific MI and
+/// specific BB can fit in MI's displacement field.
+bool SuperHBasicBlockUtils::isBBInRange(MachineInstr *MI,
+ MachineBasicBlock *DestBB,
+ unsigned MaxDisp) const {
+ unsigned PCAdj = 4;
+ unsigned BrOffset = getOffsetOf(MI) + PCAdj;
+ unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
+
+ LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB)
+ << " from " << printMBBReference(*MI->getParent())
+ << " max delta=" << MaxDisp << " from " << getOffsetOf(MI)
+ << " to " << DestOffset << " offset "
+ << int(DestOffset - BrOffset) << "\t" << *MI);
+
+ if (BrOffset <= DestOffset) {
+ // Branch before the Dest.
+ if (DestOffset-BrOffset <= MaxDisp)
+ return true;
+ } else {
+ if (BrOffset-DestOffset <= MaxDisp)
+ return true;
+ }
+ return false;
+}
+
+void SuperHBasicBlockUtils::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
+ assert(BB->getParent() == &MF &&
+ "Basic block is not a child of the current function.\n");
+
+ unsigned BBNum = BB->getNumber();
+ LLVM_DEBUG(dbgs() << "Adjust block:\n"
+ << " - name: " << BB->getName() << "\n"
+ << " - number: " << BB->getNumber() << "\n"
+ << " - function: " << MF.getName() << "\n"
+ << " - blocks: " << MF.getNumBlockIDs() << "\n");
+
+ for(unsigned i = BBNum + 1, e = MF.getNumBlockIDs(); i < e; ++i) {
+ // Get the offset and known bits at the end of the layout predecessor.
+ // Include the alignment of the current block.
+ const Align Align = MF.getBlockNumbered(i)->getAlignment();
+ const unsigned Offset = BBInfo[i - 1].postOffset(Align);
+ const unsigned KnownBits = BBInfo[i - 1].postKnownBits(Align);
+
+ // This is where block i begins. Stop if the offset is already correct,
+ // and we have updated 2 blocks. This is the maximum number of blocks
+ // changed before calling this function.
+ if (i > BBNum + 2 &&
+ BBInfo[i].Offset == Offset &&
+ BBInfo[i].KnownBits == KnownBits)
+ break;
+
+ BBInfo[i].Offset = Offset;
+ BBInfo[i].KnownBits = KnownBits;
+ }
+}
+
+
+} // namespace llvm
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
new file mode 100644
index 0000000000000..f0039cbc5eb7f
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
@@ -0,0 +1,157 @@
+//===-- SuperHBasicBlockInfo.h - Basic Block Information --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility functions and data structure for computing block size.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHBASICBLOCKINFO_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHBASICBLOCKINFO_H
+
+#include "SuperHInstrInfo.h"
+#include "SuperHMachineFunctionInfo.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cstdint>
+
+namespace llvm {
+
+struct BasicBlockInfo;
+using BBInfoVector = SmallVectorImpl<BasicBlockInfo>;
+
+/// UnknownPadding - Return the worst case padding that could result from
+/// unknown offset bits. This does not include alignment padding caused by
+/// known offset bits.
+///
+/// @param Alignment alignment
+/// @param KnownBits Number of known low offset bits.
+inline unsigned UnknownPadding(Align Alignment, unsigned KnownBits) {
+ if (KnownBits < Log2(Alignment))
+ return Alignment.value() - (1ull << KnownBits);
+ return 0;
+}
+
+/// BasicBlockInfo - Information about the offset and size of a single
+/// basic block.
+struct BasicBlockInfo {
+ /// Offset - Distance from the beginning of the function to the beginning
+ /// of this basic block.
+ ///
+ /// Offsets are computed assuming worst case padding before an aligned
+ /// block. This means that subtracting basic block offsets always gives a
+ /// conservative estimate of the real distance which may be smaller.
+ ///
+ /// Because worst case padding is used, the computed offset of an aligned
+ /// block may not actually be aligned.
+ unsigned Offset = 0;
+
+ /// Size - Size of the basic block in bytes. If the block contains
+ /// inline assembly, this is a worst case estimate.
+ ///
+ /// The size does not include any alignment padding whether from the
+ /// beginning of the block, or from an aligned jump table at the end.
+ unsigned Size = 0;
+
+ /// KnownBits - The number of low bits in Offset that are known to be
+ /// exact. The remaining bits of Offset are an upper bound.
+ uint8_t KnownBits = 0;
+
+ /// Unalign - When non-zero, the block contains instructions (inline asm)
+ /// of unknown size. The real size may be smaller than Size bytes by a
+ /// multiple of 1 << Unalign.
+ uint8_t Unalign = 0;
+
+ /// PostAlign - When > 1, the block terminator contains a .align
+ /// directive, so the end of the block is aligned to PostAlign bytes.
+ Align PostAlign;
+
+ BasicBlockInfo() = default;
+
+ /// Compute the number of known offset bits internally to this block.
+ /// This number should be used to predict worst case padding when
+ /// splitting the block.
+ unsigned internalKnownBits() const {
+ unsigned Bits = Unalign ? Unalign : KnownBits;
+ // If the block size isn't a multiple of the known bits, assume the
+ // worst case padding.
+ if (Size & ((1u << Bits) - 1))
+ Bits = llvm::countr_zero(Size);
+ return Bits;
+ }
+
+ /// Compute the offset immediately following this block. If Align is
+ /// specified, return the offset the successor block will get if it has
+ /// this alignment.
+ unsigned postOffset(Align Alignment = Align(1)) const {
+ unsigned PO = Offset + Size;
+ const Align PA = std::max(PostAlign, Alignment);
+ if (PA == Align(1))
+ return PO;
+ // Add alignment padding from the terminator.
+ return PO + UnknownPadding(PA, internalKnownBits());
+ }
+
+ /// Compute the number of known low bits of postOffset. If this block
+ /// contains inline asm, the number of known bits drops to the
+ /// instruction alignment. An aligned terminator may increase the number
+ /// of know bits.
+ /// If LogAlign is given, also consider the alignment of the next block.
+ unsigned postKnownBits(Align Align = llvm::Align(1)) const {
+ return std::max(Log2(std::max(PostAlign, Align)), internalKnownBits());
+ }
+};
+
+class SuperHBasicBlockUtils {
+
+private:
+ MachineFunction &MF;
+ const SuperHInstrInfo *TII = nullptr;
+ SmallVector<BasicBlockInfo, 8> BBInfo;
+
+public:
+ SuperHBasicBlockUtils(MachineFunction &MF) : MF(MF) {
+ TII =
+ static_cast<const SuperHInstrInfo*>(MF.getSubtarget().getInstrInfo());
+ }
+
+ void computeAllBlockSizes() {
+ BBInfo.resize(MF.getNumBlockIDs());
+ for (MachineBasicBlock &MBB : MF)
+ computeBlockSize(&MBB);
+ }
+
+ void computeBlockSize(MachineBasicBlock *MBB);
+
+ unsigned getOffsetOf(MachineInstr *MI) const;
+
+ unsigned getOffsetOf(MachineBasicBlock *MBB) const {
+ return BBInfo[MBB->getNumber()].Offset;
+ }
+
+ void adjustBBOffsetsAfter(MachineBasicBlock *MBB);
+
+ void adjustBBSize(MachineBasicBlock *MBB, int Size) {
+ BBInfo[MBB->getNumber()].Size += Size;
+ }
+
+ bool isBBInRange(MachineInstr *MI, MachineBasicBlock *DestBB,
+ unsigned MaxDisp) const;
+
+ void insert(unsigned BBNum, BasicBlockInfo BBI) {
+ BBInfo.insert(BBInfo.begin() + BBNum, BBI);
+ }
+
+ void clear() { BBInfo.clear(); }
+
+ BBInfoVector &getBBInfo() { return BBInfo; }
+
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_SUPERH_SUPERHBASICBLOCKINFO_H
diff --git a/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
new file mode 100644
index 0000000000000..226136c6fd73f
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
@@ -0,0 +1,1184 @@
+//===- SuperHConstantIslandPass.cpp - SuperH constant islands -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that splits the constant pool up into 'islands'
+// which are scattered through-out the function. This is required due to the
+// limited pc-relative displacements that SuperH has.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SuperHInstPrinter.h"
+#include "SuperHBasicBlockInfo.h"
+#include "SuperHMachineFunctionInfo.h"
+#include "SuperHSubtarget.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
+#include <memory>
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-cp-islands"
+
+#define SH_CP_ISLANDS_OPT_NAME \
+ "SH constant island placement and branch shortening pass"
+
+static cl::opt<unsigned>
+CPMaxIteration("sh-constant-island-max-iteration", cl::Hidden, cl::init(30),
+ cl::desc("The max number of iteration for converge"));
+
+namespace {
+
+ /// SuperHConstantIslands - Due to limited PC-relative displacements, SH
+ /// requires constant pool entries to be scattered among the instructions
+ /// inside a function. To do this, it completely ignores the normal LLVM
+ /// constant pool; instead, it places constants wherever it feels like with
+ /// special instructions.
+ ///
+ /// The terminology used in this pass includes:
+ /// Islands - Clumps of constants placed in the function.
+ /// Water - Potential places where an island could be formed.
+ /// CPE - A constant pool entry that has been placed somewhere, which
+ /// tracks a list of users.
+ class SuperHConstantIslands : public MachineFunctionPass {
+ public:
+ static char ID;
+
+ private:
+ std::unique_ptr<SuperHBasicBlockUtils> BBUtils = nullptr;
+
+ /// WaterList - A sorted list of basic blocks where islands could be placed
+ /// (i.e. blocks that don't fall through to the following block, due
+ /// to a return, unreachable, or unconditional branch).
+ std::vector<MachineBasicBlock*> WaterList;
+
+ /// NewWaterList - The subset of WaterList that was created since the
+ /// previous iteration by inserting unconditional branches.
+ SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
+
+ using water_iterator = std::vector<MachineBasicBlock *>::iterator;
+
+ /// CPUser - One user of a constant pool, keeping the machine instruction
+ /// pointer, the constant pool being referenced, and the max displacement
+ /// allowed from the instruction to the CP. The HighWaterMark records the
+ /// highest basic block where a new CPEntry can be placed. To ensure this
+ /// pass terminates, the CP entries are initially placed at the end of the
+ /// function and then move monotonically to lower addresses. The
+ /// exception to this rule is when the current CP entry for a particular
+ /// CPUser is out of range, but there is another CP entry for the same
+ /// constant value in range. We want to use the existing in-range CP
+ /// entry, but if it later moves out of range, the search for new water
+ /// should resume where it left off. The HighWaterMark is used to record
+ /// that point.
+ struct CPUser {
+ MachineInstr *MI;
+ MachineInstr *CPEMI;
+ MachineBasicBlock *HighWaterMark;
+ unsigned MaxDisp;
+ bool NegOk;
+ bool IsSoImm;
+ bool KnownAlignment = false;
+
+ CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,
+ bool neg, bool soimm)
+ : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(neg), IsSoImm(soimm) {
+ HighWaterMark = CPEMI->getParent();
+ }
+
+ /// getMaxDisp - Returns the maximum displacement supported by MI.
+ /// Correct for unknown alignment.
+ /// Conservatively subtract 2 bytes to handle weird alignment effects.
+ unsigned getMaxDisp() const {
+ return (KnownAlignment ? MaxDisp : MaxDisp - 2) - 2;
+ }
+ };
+
+ /// CPUsers - Keep track of all of the machine instructions that use various
+ /// constant pools and their max displacement.
+ std::vector<CPUser> CPUsers;
+
+ /// CPEntry - One per constant pool entry, keeping the machine instruction
+ /// pointer, the constpool index, and the number of CPUser's which
+ /// reference this entry.
+ struct CPEntry {
+ MachineInstr *CPEMI;
+ unsigned CPI;
+ unsigned RefCount;
+
+ CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0)
+ : CPEMI(cpemi), CPI(cpi), RefCount(rc) {}
+ };
+
+ /// CPEntries - Keep track of all of the constant pool entry machine
+ /// instructions. For each original constpool index (i.e. those that existed
+ /// upon entry to this pass), it keeps a vector of entries. Original
+ /// elements are cloned as we go along; the clones are put in the vector of
+ /// the original element, but have distinct CPIs.
+ ///
+ /// The first half of CPEntries contains generic constants, the second half
+ /// contains jump tables. Use getCombinedIndex on a generic CPEMI to look up
+ /// which vector it will be in here.
+ std::vector<std::vector<CPEntry>> CPEntries;
+
+ /// ImmBranch - One per immediate branch, keeping the machine instruction
+ /// pointer, conditional or unconditional, the max displacement,
+ /// and (if isCond is true) the corresponding unconditional branch
+ /// opcode.
+ struct ImmBranch {
+ MachineInstr *MI;
+ unsigned MaxDisp : 12;
+
+ ImmBranch(MachineInstr *mi, unsigned maxdisp)
+ : MI(mi), MaxDisp(maxdisp) {}
+ };
+
+ /// ImmBranches - Keep track of all the immediate branch instructions.
+ std::vector<ImmBranch> ImmBranches;
+
+ MachineFunction *MF;
+ MachineConstantPool *MCP;
+ const SuperHInstrInfo *TII;
+ const SuperHSubtarget *STI;
+ SuperHMachineFunctionInfo *SFI;
+ MachineDominatorTree *DT = nullptr;
+ bool isPIC;
+
+ public:
+
+ SuperHConstantIslands() : MachineFunctionPass(ID) {}
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<MachineDominatorTreeWrapperPass>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().setNoVRegs();
+ }
+
+ StringRef getPassName() const override {
+ return SH_CP_ISLANDS_OPT_NAME;
+ }
+
+ private:
+ bool BBHasFallthrough(MachineBasicBlock *MBB);
+ void doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs);
+ CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
+ Align getCPEAlign(const MachineInstr *CPEMI);
+ void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs);
+ MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI);
+ void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
+ bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI);
+ unsigned getCombinedIndex(const MachineInstr *CPEMI);
+ int findInRangeCPEntry(CPUser& U, unsigned UserOffset);
+ bool findAvailableWater(CPUser&U, unsigned UserOffset,
+ water_iterator &WaterIter, bool CloserWater);
+ void createNewWater(unsigned CPUserIndex, unsigned UserOffset,
+ MachineBasicBlock *&NewMBB);
+ bool handleConstantPoolUser(unsigned CPUserIndex, bool CloserWater);
+ void removeDeadCPEMI(MachineInstr *CPEMI);
+ bool removeUnusedCPEntries();
+ bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
+ MachineInstr *CPEMI, unsigned Disp, bool NegOk,
+ bool DoDump = false);
+ bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water,
+ CPUser &U, unsigned &Growth);
+ bool fixupImmediateBr(ImmBranch &Br);
+
+ unsigned getUserOffset(CPUser&) const;
+ void verify();
+
+ bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
+ unsigned Disp, bool NegativeOK, bool IsSoImm = false);
+ bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
+ const CPUser &U) {
+ return isOffsetInRange(UserOffset, TrialOffset,
+ U.getMaxDisp(), U.NegOk, U.IsSoImm);
+ }
+
+ };
+
+} // end anonymous namespace
+
+char SuperHConstantIslands::ID = 0;
+
+
+
+
+//===----------------------------------------------------------------------===//
+// HELPERS
+//===----------------------------------------------------------------------===//
+
+// Align blocks where the previous block does not fall through. This may add
+// extra NOP's but they will not be executed. It uses the PrefLoopAlignment as a
+// measure of how much to align, and only runs at CodeGenOptLevel::Aggressive.
+static bool AlignBlocks(MachineFunction *MF, const SuperHSubtarget *STI) {
+ if (MF->getTarget().getOptLevel() != CodeGenOptLevel::Aggressive ||
+ MF->getFunction().hasOptSize())
+ return false;
+
+ auto *TLI = STI->getTargetLowering();
+ const Align Alignment = TLI->getPrefLoopAlignment();
+ if (Alignment < 4)
+ return false;
+
+ bool Changed = false;
+ bool PrevCanFallthrough = true;
+ for (auto &MBB : *MF) {
+ if (!PrevCanFallthrough) {
+ Changed = true;
+ MBB.setAlignment(Alignment);
+ }
+ }
+
+ return Changed;
+}
+
+/// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB
+/// ID.
+static bool CompareMBBNumbers(const MachineBasicBlock *LHS,
+ const MachineBasicBlock *RHS) {
+ return LHS->getNumber() < RHS->getNumber();
+}
+
+/// getDispRange - Returns the maximum displacement that can fit in
+/// the specific unconditional branch instruction.
+static inline unsigned getDispRange(int Opc) {
+ return ((1<<8)-1)*4;
+}
+
+/// isOffsetInRange - Checks whether UserOffset (the location of a constant pool
+/// reference) is within MaxDisp of TrialOffset (a proposed location of a
+/// constant pool entry).
+/// UserOffset is computed by getUserOffset above to include PC adjustments. If
+/// the mod 4 alignment of UserOffset is not known, the uncertainty must be
+/// subtracted from MaxDisp instead. CPUser::getMaxDisp() does that.
+bool SuperHConstantIslands::isOffsetInRange(unsigned UserOffset,
+ unsigned TrialOffset, unsigned MaxDisp,
+ bool NegativeOK, bool IsSoImm) {
+ if (UserOffset <= TrialOffset) {
+ // User before the Trial.
+ if (TrialOffset - UserOffset <= MaxDisp)
+ return true;
+ // FIXME: Make use full range of soimm values.
+ } else if (NegativeOK) {
+ if (UserOffset - TrialOffset <= MaxDisp)
+ return true;
+ // FIXME: Make use full range of soimm values.
+ }
+ return false;
+}
+
+/// BBHasFallthrough - Return true if the specified basic block can fallthrough
+/// into the block immediately after it.
+bool SuperHConstantIslands::BBHasFallthrough(MachineBasicBlock *MBB) {
+ // Get the next machine basic block in the function.
+ MachineFunction::iterator MBBI = MBB->getIterator();
+ // Can't fall off end of function.
+ if (std::next(MBBI) == MBB->getParent()->end())
+ return false;
+
+ MachineBasicBlock *NextBB = &*std::next(MBBI);
+ if (!MBB->isSuccessor(NextBB))
+ return false;
+
+ // Try to analyze the end of the block. A potential fallthrough may already
+ // have an unconditional branch for whatever reason.
+ MachineBasicBlock *TBB, *FBB;
+ SmallVector<MachineOperand, 4> Cond;
+ bool TooDifficult = TII->analyzeBranch(*MBB, TBB, FBB, Cond);
+ return TooDifficult || FBB == nullptr;
+}
+
+/// getCPEAlign - Returns the required alignment of the constant pool entry
+/// represented by CPEMI.
+Align SuperHConstantIslands::getCPEAlign(const MachineInstr *CPEMI) {
+ unsigned CPI = getCombinedIndex(CPEMI);
+ assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");
+ return MCP->getConstants()[CPI].getAlign();
+}
+
+/// isWaterInRange - Returns true if a CPE placed after the specified
+/// Water (a basic block) will be in range for the specific MI.
+///
+/// Compute how much the function will grow by inserting a CPE after Water.
+bool SuperHConstantIslands::isWaterInRange(unsigned UserOffset,
+ MachineBasicBlock* Water, CPUser &U,
+ unsigned &Growth) {
+ BBInfoVector &BBInfo = BBUtils->getBBInfo();
+ const Align CPEAlign = getCPEAlign(U.CPEMI);
+ const unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPEAlign);
+ unsigned NextBlockOffset;
+ Align NextBlockAlignment;
+ MachineFunction::const_iterator NextBlock = Water->getIterator();
+ if (++NextBlock == MF->end()) {
+ NextBlockOffset = BBInfo[Water->getNumber()].postOffset();
+ } else {
+ NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
+ NextBlockAlignment = NextBlock->getAlignment();
+ }
+ unsigned Size = U.CPEMI->getOperand(2).getImm();
+ unsigned CPEEnd = CPEOffset + Size;
+
+ // The CPE may be able to hide in the alignment padding before the next
+ // block. It may also cause more padding to be required if it is more aligned
+ // that the next block.
+ if (CPEEnd > NextBlockOffset) {
+ Growth = CPEEnd - NextBlockOffset;
+ // Compute the padding that would go at the end of the CPE to align the next
+ // block.
+ Growth += offsetToAlignment(CPEEnd, NextBlockAlignment);
+
+ // If the CPE is to be inserted before the instruction, that will raise
+ // the offset of the instruction. Also account for unknown alignment padding
+ // in blocks between CPE and the user.
+ if (CPEOffset < UserOffset)
+ UserOffset += Growth + UnknownPadding(MF->getAlignment(), Log2(CPEAlign));
+ } else
+ // CPE fits in existing padding.
+ Growth = 0;
+
+ return isOffsetInRange(UserOffset, CPEOffset, U);
+}
+
+/// isCPEntryInRange - Returns true if the distance between specific MI and
+/// specific ConstPool entry instruction can fit in MI's displacement field.
+bool SuperHConstantIslands::isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
+ MachineInstr *CPEMI, unsigned MaxDisp,
+ bool NegOk, bool DoDump) {
+ unsigned CPEOffset = BBUtils->getOffsetOf(CPEMI);
+
+ if (DoDump) {
+ LLVM_DEBUG({
+ BBInfoVector &BBInfo = BBUtils->getBBInfo();
+ unsigned Block = MI->getParent()->getNumber();
+ const BasicBlockInfo &BBI = BBInfo[Block];
+ dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm()
+ << " max delta=" << MaxDisp
+ << format(" insn address=%#x", UserOffset) << " in "
+ << printMBBReference(*MI->getParent()) << ": "
+ << format("%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI
+ << format("CPE address=%#x offset=%+d: ", CPEOffset,
+ int(CPEOffset - UserOffset));
+ });
+ }
+
+ return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
+}
+
+/// getUserOffset - Compute the offset of U.MI as seen by the hardware
+/// displacement computation. Update U.KnownAlignment to match its current
+/// basic block location.
+unsigned SuperHConstantIslands::getUserOffset(CPUser &U) const {
+ unsigned UserOffset = BBUtils->getOffsetOf(U.MI);
+
+ SmallVectorImpl<BasicBlockInfo> &BBInfo = BBUtils->getBBInfo();
+ const BasicBlockInfo &BBI = BBInfo[U.MI->getParent()->getNumber()];
+ unsigned KnownBits = BBI.internalKnownBits();
+
+ // The value read from PC is offset from the actual instruction address.
+ UserOffset += 4;
+
+ // Because of inline assembly, we may not know the alignment (mod 4) of U.MI.
+ // Make sure U.getMaxDisp() returns a constrained range.
+ U.KnownAlignment = (KnownBits >= 2);
+ return UserOffset;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// BASE IMPLEMENTATION
+//===----------------------------------------------------------------------===//
+
+bool SuperHConstantIslands::runOnMachineFunction(MachineFunction &mf) {
+ MF = &mf;
+ MCP = MF->getConstantPool();
+ BBUtils = std::make_unique<SuperHBasicBlockUtils>(mf);
+
+ LLVM_DEBUG(dbgs() << "***** SuperHConstantIslands: "
+ << MCP->getConstants().size() << " CP entries, aligned to "
+ << MCP->getConstantPoolAlign().value() << " bytes *****\n");
+
+ STI = &MF->getSubtarget<SuperHSubtarget>();
+ TII = STI->getInstrInfo();
+ isPIC = STI->getTargetLowering()->isPositionIndependent();
+ SFI = MF->getInfo<SuperHMachineFunctionInfo>();
+ DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
+
+ // Renumber all of the machine basic blocks in the function, guaranteeing that
+ // the numbers agree with the position of the block in the function.
+ MF->RenumberBlocks();
+
+ bool MadeChange = false;
+
+ // Align any non-fallthrough blocks
+ MadeChange |= AlignBlocks(MF, STI);
+
+ // Perform the initial placement of the constant pool entries. To start with,
+ // we put them all at the end of the function.
+ std::vector<MachineInstr*> CPEMIs;
+ if (!MCP->isEmpty())
+ doInitialConstPlacement(CPEMIs);
+
+
+ // Iteratively place constant pool entries and fix up branches until there
+ // is no change.
+ unsigned NoCPIters = 0, NoBRIters = 0;
+ while (true) {
+ LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << " with " <<
+ CPUsers.size() << " entries..." << '\n');
+ bool CPChange = false;
+ for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
+ // For most inputs, it converges in no more than 5 iterations.
+ // If it doesn't end in 10, the input may have huge BB or many CPEs.
+ // In this case, we will try different heuristics.
+ CPChange |= handleConstantPoolUser(i, NoCPIters >= CPMaxIteration / 2);
+ if (CPChange && ++NoCPIters > CPMaxIteration)
+ report_fatal_error("Constant Island pass failed to converge!");
+
+ // Clear NewWaterList now. If we split a block for branches, it should
+ // appear as "new water" for the next iteration of constant pool placement.
+ NewWaterList.clear();
+
+ LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << " with " <<
+ ImmBranches.size() << " entries..." << '\n');
+ bool BRChange = false;
+ for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) {
+ // Note: fixupImmediateBr can append to ImmBranches.
+ BRChange |= fixupImmediateBr(ImmBranches[i]);
+ }
+ if (BRChange && ++NoBRIters > 30)
+ report_fatal_error("Branch Fix Up pass failed to converge!");
+
+ if (!CPChange && !BRChange)
+ break;
+ MadeChange = true;
+ }
+
+ BBUtils->clear();
+ CPUsers.clear();
+ CPEntries.clear();
+ WaterList.clear();
+ ImmBranches.clear();
+ return MadeChange;
+}
+
+/// initializeFunctionInfo - Do the initial scan of the function, building up
+/// information about the sizes of each block, the location of all the water,
+/// and finding all of the constant pool users.
+void SuperHConstantIslands::
+initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
+
+ BBUtils->computeAllBlockSizes();
+ BBInfoVector &BBInfo = BBUtils->getBBInfo();
+
+ // The known bits of the entry block offset are determined by the function
+ // alignment.
+ BBInfo.front().KnownBits = Log2(MF->getAlignment());
+
+ // Compute block offsets and known bits.
+ BBUtils->adjustBBOffsetsAfter(&MF->front());
+
+ // Now go back through the instructions and build up our data structures.
+ for (MachineBasicBlock &MBB : *MF) {
+
+ // If this block doesn't fall through into the next MBB, then this is
+ // 'water' that a constant pool island could be placed.
+ if (!BBHasFallthrough(&MBB))
+ WaterList.push_back(&MBB);
+
+ for (MachineInstr &I : MBB) {
+ if (I.isDebugInstr())
+ continue;
+
+ unsigned Opc = I.getOpcode();
+ if (I.isBranch()) {
+ unsigned Bits = 8;
+ unsigned Scale = 4;
+ switch (Opc) {
+ default:
+ continue;
+
+ case SH::BF:
+ case SH::BFS:
+ case SH::BT:
+ case SH::BTS:
+ Bits = 8;
+ Scale = 4;
+ break;
+ case SH::BRA:
+ case SH::BSR:
+ Bits = 12;
+ Scale = 4;
+ break;
+ }
+
+
+ // Record this immediate branch.
+ unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
+ ImmBranches.push_back(ImmBranch(&I, MaxOffs));
+ }
+
+ if (Opc == SH::CONSTPOOL_ENTRY)
+ continue;
+
+ // Scan the instructions for constant pool operands.
+ for (unsigned op = 0, e = I.getNumOperands(); op != e; ++op) {
+ if (I.getOperand(op).isCPI()) {
+ bool NegOk = false;
+ bool IsSoImm = false;
+
+ unsigned CPI = I.getOperand(op).getIndex();
+ MachineInstr *CPEMI = CPEMIs[CPI];
+ unsigned MaxOffs = ((1 << 8)-1) * 4;
+ CPUsers.push_back(CPUser(&I, CPEMI, MaxOffs, NegOk, IsSoImm));
+
+ // Increment corresponding CPEntry reference count.
+ CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
+ assert(CPE && "Cannot find a corresponding CPEntry!");
+ CPE->RefCount++;
+
+ // Instructions can only use one CP entry, don't bother scanning the
+ // rest of the operands.
+ break;
+
+ }
+ }
+ }
+ }
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// CONSTPOOL MANAGMENT
+//===----------------------------------------------------------------------===//
+
+/// removeDeadCPEMI - Remove a dead constant pool entry instruction. Update
+/// sizes and offsets of impacted basic blocks.
+void SuperHConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
+ MachineBasicBlock *CPEBB = CPEMI->getParent();
+ unsigned Size = CPEMI->getOperand(2).getImm();
+ CPEMI->eraseFromParent();
+ BBInfoVector &BBInfo = BBUtils->getBBInfo();
+ BBUtils->adjustBBSize(CPEBB, -Size);
+ // All succeeding offsets have the current size value added in, fix this.
+ if (CPEBB->empty()) {
+ BBInfo[CPEBB->getNumber()].Size = 0;
+
+ // This block no longer needs to be aligned.
+ CPEBB->setAlignment(Align(1));
+ } else {
+ // Entries are sorted by descending alignment, so realign from the front.
+ CPEBB->setAlignment(getCPEAlign(&*CPEBB->begin()));
+ }
+
+ BBUtils->adjustBBOffsetsAfter(CPEBB);
+}
+
+/// removeUnusedCPEntries - Remove constant pool entries whose refcounts
+/// are zero.
+bool SuperHConstantIslands::removeUnusedCPEntries() {
+ unsigned MadeChange = false;
+ for (std::vector<CPEntry> &CPEs : CPEntries) {
+ for (CPEntry &CPE : CPEs) {
+ if (CPE.RefCount == 0 && CPE.CPEMI) {
+ removeDeadCPEMI(CPE.CPEMI);
+ CPE.CPEMI = nullptr;
+ MadeChange = true;
+ }
+ }
+ }
+ return MadeChange;
+}
+
+/// decrementCPEReferenceCount - find the constant pool entry with index CPI
+/// and instruction CPEMI, and decrement its refcount. If the refcount
+/// becomes 0 remove the entry and instruction. Returns true if we removed
+/// the entry, false if we didn't.
+bool SuperHConstantIslands::decrementCPEReferenceCount(unsigned CPI,
+ MachineInstr *CPEMI) {
+ // Find the old entry. Eliminate it if it is no longer used.
+ CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
+ assert(CPE && "Unexpected!");
+ if (--CPE->RefCount == 0) {
+ removeDeadCPEMI(CPEMI);
+ CPE->CPEMI = nullptr;
+ return true;
+ }
+ return false;
+}
+
+unsigned SuperHConstantIslands::getCombinedIndex(const MachineInstr *CPEMI) {
+ if (CPEMI->getOperand(1).isCPI())
+ return CPEMI->getOperand(1).getIndex();
+
+ return 0;
+}
+/// LookForCPEntryInRange - see if the currently referenced CPE is in range;
+/// if not, see if an in-range clone of the CPE is in range, and if so,
+/// change the data structures so the user references the clone. Returns:
+/// 0 = no existing entry found
+/// 1 = entry found, and there were no code insertions or deletions
+/// 2 = entry found, and there were code insertions or deletions
+int SuperHConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) {
+ MachineInstr *UserMI = U.MI;
+ MachineInstr *CPEMI = U.CPEMI;
+
+ // Check to see if the CPE is already in-range.
+ if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,
+ true)) {
+ LLVM_DEBUG(dbgs() << "In range\n");
+ return 1;
+ }
+
+ // No. Look for previously created clones of the CPE that are in range.
+ unsigned CPI = getCombinedIndex(CPEMI);
+ std::vector<CPEntry> &CPEs = CPEntries[CPI];
+ for (CPEntry &CPE : CPEs) {
+ // We already tried this one
+ if (CPE.CPEMI == CPEMI)
+ continue;
+ // Removing CPEs can leave empty entries, skip
+ if (CPE.CPEMI == nullptr)
+ continue;
+ if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, U.getMaxDisp(),
+ U.NegOk)) {
+ LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" << CPE.CPI
+ << "\n");
+ // Point the CPUser node to the replacement
+ U.CPEMI = CPE.CPEMI;
+ // Change the CPI in the instruction operand to refer to the clone.
+ for (MachineOperand &MO : UserMI->operands())
+ if (MO.isCPI()) {
+ MO.setIndex(CPE.CPI);
+ break;
+ }
+ // Adjust the refcount of the clone...
+ CPE.RefCount++;
+ // ...and the original. If we didn't remove the old entry, none of the
+ // addresses changed, so we don't need another pass.
+ return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
+ }
+ }
+ return 0;
+}
+
+/// handleConstantPoolUser - Analyze the specified user, checking to see if it
+/// is out-of-range. If so, pick up the constant pool value and move it some
+/// place in-range. Return true if we changed any addresses (thus must run
+/// another pass of branch lengthening), false otherwise.
+bool SuperHConstantIslands::handleConstantPoolUser(unsigned CPUserIndex,
+ bool CloserWater) {
+ CPUser &U = CPUsers[CPUserIndex];
+ MachineInstr *UserMI = U.MI;
+ MachineInstr *CPEMI = U.CPEMI;
+ unsigned CPI = getCombinedIndex(CPEMI);
+ unsigned Size = CPEMI->getOperand(2).getImm();
+ // Compute this only once, it's expensive.
+ unsigned UserOffset = getUserOffset(U);
+
+ // See if the current entry is within range, or there is a clone of it
+ // in range.
+ int result = findInRangeCPEntry(U, UserOffset);
+ if (result==1) return false;
+ else if (result==2) return true;
+
+ // No existing clone of this CPE is within range.
+ // We will be generating a new clone. Get a UID for it.
+ unsigned ID = SFI->createConstIndex();
+
+ // Look for water where we can place this CPE.
+ MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
+ MachineBasicBlock *NewMBB;
+ water_iterator IP;
+ if (findAvailableWater(U, UserOffset, IP, CloserWater)) {
+ LLVM_DEBUG(dbgs() << "Found water in range\n");
+ MachineBasicBlock *WaterBB = *IP;
+
+ // If the original WaterList entry was "new water" on this iteration,
+ // propagate that to the new island. This is just keeping NewWaterList
+ // updated to match the WaterList, which will be updated below.
+ if (NewWaterList.erase(WaterBB))
+ NewWaterList.insert(NewIsland);
+
+ // The new CPE goes before the following block (NewMBB).
+ NewMBB = &*++WaterBB->getIterator();
+ } else {
+ // No water found.
+ LLVM_DEBUG(dbgs() << "No water found\n");
+ createNewWater(CPUserIndex, UserOffset, NewMBB);
+
+ // splitBlockBeforeInstr adds to WaterList, which is important when it is
+ // called while handling branches so that the water will be seen on the
+ // next iteration for constant pools, but in this context, we don't want
+ // it. Check for this so it will be removed from the WaterList.
+ // Also remove any entry from NewWaterList.
+ MachineBasicBlock *WaterBB = &*--NewMBB->getIterator();
+ IP = find(WaterList, WaterBB);
+ if (IP != WaterList.end())
+ NewWaterList.erase(WaterBB);
+
+ // We are adding new water. Update NewWaterList.
+ NewWaterList.insert(NewIsland);
+ }
+ // Always align the new block because CP entries can be smaller than 4
+ // bytes. Be careful not to decrease the existing alignment, e.g. NewMBB may
+ // be an already aligned constant pool block.
+ const Align Alignment = Align(4);
+ if (NewMBB->getAlignment() < Alignment)
+ NewMBB->setAlignment(Alignment);
+
+ // Remove the original WaterList entry; we want subsequent insertions in
+ // this vicinity to go after the one we're about to insert. This
+ // considerably reduces the number of times we have to move the same CPE
+ // more than once and is also important to ensure the algorithm terminates.
+ if (IP != WaterList.end())
+ WaterList.erase(IP);
+
+ // Okay, we know we can put an island before NewMBB now, do it!
+ MF->insert(NewMBB->getIterator(), NewIsland);
+
+ // Update internal data structures to account for the newly inserted MBB.
+ updateForInsertedWaterBlock(NewIsland);
+
+ // Now that we have an island to add the CPE to, clone the original CPE and
+ // add it to the island.
+ U.HighWaterMark = NewIsland;
+ U.CPEMI = BuildMI(NewIsland, DebugLoc(), CPEMI->getDesc())
+ .addImm(ID)
+ .add(CPEMI->getOperand(1))
+ .addImm(Size);
+ CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1));
+
+ // Decrement the old entry, and remove it if refcount becomes 0.
+ decrementCPEReferenceCount(CPI, CPEMI);
+
+ // Mark the basic block as aligned as required by the const-pool entry.
+ NewIsland->setAlignment(getCPEAlign(U.CPEMI));
+
+ // Increase the size of the island block to account for the new entry.
+ BBUtils->adjustBBSize(NewIsland, Size);
+ BBUtils->adjustBBOffsetsAfter(&*--NewIsland->getIterator());
+
+ // Finally, change the CPI in the instruction operand to be ID.
+ for (MachineOperand &MO : UserMI->operands())
+ if (MO.isCPI()) {
+ MO.setIndex(ID);
+ break;
+ }
+
+ LLVM_DEBUG(
+ dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI
+ << format(" offset=%#x\n",
+ BBUtils->getBBInfo()[NewIsland->getNumber()].Offset));
+
+ return true;
+}
+
+/// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI,
+/// look up the corresponding CPEntry.
+SuperHConstantIslands::CPEntry *
+SuperHConstantIslands::findConstPoolEntry(unsigned CPI,
+ const MachineInstr *CPEMI) {
+ std::vector<CPEntry> &CPEs = CPEntries[CPI];
+ // Number of entries per constpool index should be small, just do a
+ // linear search.
+ for (CPEntry &CPE : CPEs)
+ if (CPE.CPEMI == CPEMI)
+ return &CPE;
+ return nullptr;
+}
+
+/// findAvailableWater - Look for an existing entry in the WaterList in which
+/// we can place the CPE referenced from U so it's within range of U's MI.
+/// Returns true if found, false if not. If it returns true, WaterIter
+/// is set to the WaterList entry. For Thumb, prefer water that will not
+/// introduce padding to water that will. To ensure that this pass
+/// terminates, the CPE location for a particular CPUser is only allowed to
+/// move to a lower address, so search backward from the end of the list and
+/// prefer the first water that is in range.
+bool SuperHConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
+ water_iterator &WaterIter,
+ bool CloserWater) {
+ if (WaterList.empty())
+ return false;
+
+ unsigned BestGrowth = ~0u;
+ // The nearest water without splitting the UserBB is right after it.
+ // If the distance is still large (we have a big BB), then we need to split it
+ // if we don't converge after certain iterations. This helps the following
+ // situation to converge:
+ // BB0:
+ // Big BB
+ // BB1:
+ // Constant Pool
+ // When a CP access is out of range, BB0 may be used as water. However,
+ // inserting islands between BB0 and BB1 makes other accesses out of range.
+ MachineBasicBlock *UserBB = U.MI->getParent();
+ BBInfoVector &BBInfo = BBUtils->getBBInfo();
+ const Align CPEAlign = getCPEAlign(U.CPEMI);
+ unsigned MinNoSplitDisp = BBInfo[UserBB->getNumber()].postOffset(CPEAlign);
+ if (CloserWater && MinNoSplitDisp > U.getMaxDisp() / 2)
+ return false;
+ for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();;
+ --IP) {
+ MachineBasicBlock* WaterBB = *IP;
+ // Check if water is in range and is either at a lower address than the
+ // current "high water mark" or a new water block that was created since
+ // the previous iteration by inserting an unconditional branch. In the
+ // latter case, we want to allow resetting the high water mark back to
+ // this new water since we haven't seen it before. Inserting branches
+ // should be relatively uncommon and when it does happen, we want to be
+ // sure to take advantage of it for all the CPEs near that block, so that
+ // we don't insert more branches than necessary.
+ // When CloserWater is true, we try to find the lowest address after (or
+ // equal to) user MI's BB no matter of padding growth.
+ unsigned Growth;
+ if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
+ (WaterBB->getNumber() < U.HighWaterMark->getNumber() ||
+ NewWaterList.count(WaterBB) || WaterBB == U.MI->getParent()) &&
+ Growth < BestGrowth) {
+ // This is the least amount of required padding seen so far.
+ BestGrowth = Growth;
+ WaterIter = IP;
+ LLVM_DEBUG(dbgs() << "Found water after " << printMBBReference(*WaterBB)
+ << " Growth=" << Growth << '\n');
+
+ if (CloserWater && WaterBB == U.MI->getParent())
+ return true;
+ // Keep looking unless it is perfect and we're not looking for the lowest
+ // possible address.
+ if (!CloserWater && BestGrowth == 0)
+ return true;
+ }
+ if (IP == B)
+ break;
+ }
+ return BestGrowth != ~0u;
+}
+
+/// createNewWater - No existing WaterList entry will work for
+/// CPUsers[CPUserIndex], so create a place to put the CPE. The end of the
+/// block is used if in range, and the conditional branch munged so control
+/// flow is correct. Otherwise the block is split to create a hole with an
+/// unconditional branch around it. In either case NewMBB is set to a
+/// block following which the new island can be inserted (the WaterList
+/// is not adjusted).
+void SuperHConstantIslands::createNewWater(unsigned CPUserIndex,
+ unsigned UserOffset,
+ MachineBasicBlock *&NewMBB) {
+ CPUser &U = CPUsers[CPUserIndex];
+ MachineInstr *UserMI = U.MI;
+ MachineInstr *CPEMI = U.CPEMI;
+ const Align CPEAlign = getCPEAlign(CPEMI);
+ MachineBasicBlock *UserMBB = UserMI->getParent();
+ BBInfoVector &BBInfo = BBUtils->getBBInfo();
+ const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()];
+
+ // If the block does not end in an unconditional branch already, and if the
+ // end of the block is within range, make new water there. (The addition
+ // below is for the unconditional branch we will be adding: 4 bytes on ARM +
+ // Thumb2, 2 on Thumb1.
+ if (BBHasFallthrough(UserMBB)) {
+ // Size of branch to insert.
+ unsigned Delta = 4;
+ // Compute the offset where the CPE will begin.
+ unsigned CPEOffset = UserBBI.postOffset(CPEAlign) + Delta;
+
+ if (isOffsetInRange(UserOffset, CPEOffset, U)) {
+ LLVM_DEBUG(dbgs() << "Split at end of " << printMBBReference(*UserMBB)
+ << format(", expected CPE offset %#x\n", CPEOffset));
+ NewMBB = &*++UserMBB->getIterator();
+
+ // Add an unconditional branch from UserMBB to fallthrough block. Record
+ // it for branch lengthening; this new branch will not get out of range,
+ // but if the preceding conditional branch is out of range, the targets
+ // will be exchanged, and the altered branch may be out of range, so the
+ // machinery has to know about it.
+ BuildMI(UserMBB, DebugLoc(), TII->get(SH::BRA))
+ .addMBB(NewMBB);
+
+ unsigned MaxDisp = getDispRange(SH::BRA);
+ ImmBranches.push_back(ImmBranch(&UserMBB->back(), MaxDisp));
+ BBUtils->computeBlockSize(UserMBB);
+ BBUtils->adjustBBOffsetsAfter(UserMBB);
+ return;
+ }
+ }
+
+ // What a big block. Find a place within the block to split it. This is a
+ // little tricky on Thumb1 since instructions are 2 bytes and constant pool
+ // entries are 4 bytes: if instruction I references island CPE, and
+ // instruction I+1 references CPE', it will not work well to put CPE as far
+ // forward as possible, since then CPE' cannot immediately follow it (that
+ // location is 2 bytes farther away from I+1 than CPE was from I) and we'd
+ // need to create a new island. So, we make a first guess, then walk through
+ // the instructions between the one currently being looked at and the
+ // possible insertion point, and make sure any other instructions that
+ // reference CPEs will be able to use the same island area; if not, we back
+ // up the insertion point.
+
+ // Try to split the block so it's fully aligned. Compute the latest split
+ // point where we can add a 4-byte branch instruction, and then align to
+ // Align which is the largest possible alignment in the function.
+ const Align Align = MF->getAlignment();
+ assert(Align >= CPEAlign && "Over-aligned constant pool entry");
+ unsigned KnownBits = UserBBI.internalKnownBits();
+ unsigned UPad = UnknownPadding(Align, KnownBits);
+ unsigned BaseInsertOffset = UserOffset + U.getMaxDisp() - UPad;
+ LLVM_DEBUG(dbgs() << format("Split in middle of big block before %#x",
+ BaseInsertOffset));
+
+ // The 4 in the following is for the unconditional branch we'll be inserting
+ // (allows for long branch on Thumb1). Alignment of the island is handled
+ // inside isOffsetInRange.
+ BaseInsertOffset -= 4;
+
+ LLVM_DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset)
+ << " la=" << Log2(Align) << " kb=" << KnownBits
+ << " up=" << UPad << '\n');
+
+ unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +
+ CPEMI->getOperand(2).getImm();
+ MachineBasicBlock::iterator MI = UserMI;
+ ++MI;
+ unsigned CPUIndex = CPUserIndex+1;
+ unsigned NumCPUsers = CPUsers.size();
+ for (unsigned Offset = UserOffset + TII->getInstSizeInBytes(*UserMI);
+ Offset < BaseInsertOffset;
+ Offset += TII->getInstSizeInBytes(*MI), MI = std::next(MI)) {
+ assert(MI != UserMBB->end() && "Fell off end of block");
+ if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == &*MI) {
+ CPUser &U = CPUsers[CPUIndex];
+ if (!isOffsetInRange(Offset, EndInsertOffset, U)) {
+ // Shift intertion point by one unit of alignment so it is within reach.
+ BaseInsertOffset -= Align.value();
+ EndInsertOffset -= Align.value();
+ }
+ // This is overly conservative, as we don't account for CPEMIs being
+ // reused within the block, but it doesn't matter much. Also assume CPEs
+ // are added in order with alignment padding. We may eventually be able
+ // to pack the aligned CPEs better.
+ EndInsertOffset += U.CPEMI->getOperand(2).getImm();
+ CPUIndex++;
+ }
+ }
+
+ --MI;
+
+ // We really must not split an IT block.
+ NewMBB = splitBlockBeforeInstr(&*MI);
+}
+
+/// updateForInsertedWaterBlock - When a block is newly inserted into the
+/// machine function, it upsets all of the block numbers. Renumber the blocks
+/// and update the arrays that parallel this numbering.
+void SuperHConstantIslands::updateForInsertedWaterBlock(MachineBasicBlock *NewBB) {
+ // Renumber the MBB's to keep them consecutive.
+ NewBB->getParent()->RenumberBlocks(NewBB);
+
+ // Insert an entry into BBInfo to align it properly with the (newly
+ // renumbered) block numbers.
+ BBUtils->insert(NewBB->getNumber(), BasicBlockInfo());
+
+ // Next, update WaterList. Specifically, we need to add NewMBB as having
+ // available water after it.
+ water_iterator IP = llvm::lower_bound(WaterList, NewBB, CompareMBBNumbers);
+ WaterList.insert(IP, NewBB);
+}
+
+/// Split the basic block containing MI into two blocks, which are joined by
+/// an unconditional branch. Update data structures and renumber blocks to
+/// account for this change and returns the newly created block.
+MachineBasicBlock *SuperHConstantIslands::splitBlockBeforeInstr(MachineInstr *MI) {
+ MachineBasicBlock *OrigBB = MI->getParent();
+
+ // Collect liveness information at MI.
+ LivePhysRegs LRs(*MF->getSubtarget().getRegisterInfo());
+ LRs.addLiveOuts(*OrigBB);
+ auto LivenessEnd = ++MachineBasicBlock::iterator(MI).getReverse();
+ for (MachineInstr &LiveMI : make_range(OrigBB->rbegin(), LivenessEnd))
+ LRs.stepBackward(LiveMI);
+
+ // Create a new MBB for the code after the OrigBB.
+ MachineBasicBlock *NewBB =
+ MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
+ MachineFunction::iterator MBBI = ++OrigBB->getIterator();
+ MF->insert(MBBI, NewBB);
+
+ // Splice the instructions starting with MI over to NewBB.
+ NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
+
+ // Add an unconditional branch from OrigBB to NewBB.
+ // Note the new unconditional branch is not being recorded.
+ // There doesn't seem to be meaningful DebugInfo available; this doesn't
+ // correspond to anything in the source.
+ BuildMI(OrigBB, DebugLoc(), TII->get(SH::BRA)).addMBB(NewBB);
+
+ // Update the CFG. All succs of OrigBB are now succs of NewBB.
+ NewBB->transferSuccessors(OrigBB);
+
+ // OrigBB branches to NewBB.
+ OrigBB->addSuccessor(NewBB);
+
+ // Update live-in information in the new block.
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+ for (MCPhysReg L : LRs)
+ if (!MRI.isReserved(L))
+ NewBB->addLiveIn(L);
+
+ // Update internal data structures to account for the newly inserted MBB.
+ // This is almost the same as updateForInsertedWaterBlock, except that
+ // the Water goes after OrigBB, not NewBB.
+ MF->RenumberBlocks(NewBB);
+
+ // Insert an entry into BBInfo to align it properly with the (newly
+ // renumbered) block numbers.
+ BBUtils->insert(NewBB->getNumber(), BasicBlockInfo());
+
+ // Next, update WaterList. Specifically, we need to add OrigMBB as having
+ // available water after it (but not if it's already there, which happens
+ // when splitting before a conditional branch that is followed by an
+ // unconditional branch - in that case we want to insert NewBB).
+ water_iterator IP = llvm::lower_bound(WaterList, OrigBB, CompareMBBNumbers);
+ MachineBasicBlock* WaterBB = *IP;
+ if (WaterBB == OrigBB)
+ WaterList.insert(std::next(IP), NewBB);
+ else
+ WaterList.insert(IP, OrigBB);
+ NewWaterList.insert(OrigBB);
+
+ // Figure out how large the OrigBB is. As the first half of the original
+ // block, it cannot contain a tablejump. The size includes
+ // the new jump we added. (It should be possible to do this without
+ // recounting everything, but it's very confusing, and this is rarely
+ // executed.)
+ BBUtils->computeBlockSize(OrigBB);
+
+ // Figure out how large the NewMBB is. As the second half of the original
+ // block, it may contain a tablejump.
+ BBUtils->computeBlockSize(NewBB);
+
+ // All BBOffsets following these blocks must be modified.
+ BBUtils->adjustBBOffsetsAfter(OrigBB);
+
+ return NewBB;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// CONST PLACEMENT
+//===----------------------------------------------------------------------===//
+
+/// Perform the initial placement of the regular constant pool entries.
+/// To start with, we put them all at the end of the function.
+void
+SuperHConstantIslands::doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs) {
+
+ // Create the basic block to hold the CPE's.
+ MachineBasicBlock *BB = MF->CreateMachineBasicBlock();
+ MF->push_back(BB);
+
+ // MachineConstantPool measures alignment in bytes.
+ const Align MaxAlign = MCP->getConstantPoolAlign();
+ const unsigned MaxLogAlign = Log2(MaxAlign);
+
+ // Mark the basic block as required by the const-pool.
+ BB->setAlignment(MaxAlign);
+
+ // The function needs to be as aligned as the basic blocks. The linker may
+ // move functions around based on their alignment.
+ // Special case: halfword literals still need word alignment on the function.
+ Align FuncAlign = MaxAlign;
+ if (MaxAlign == 2)
+ FuncAlign = Align(4);
+ MF->ensureAlignment(FuncAlign);
+
+ // Order the entries in BB by descending alignment. That ensures correct
+ // alignment of all entries as long as BB is sufficiently aligned. Keep
+ // track of the insertion point for each alignment. We are going to bucket
+ // sort the entries as they are created.
+ SmallVector<MachineBasicBlock::iterator, 8> InsPoint(MaxLogAlign + 1,
+ BB->end());
+
+ // Add all of the constants from the constant pool to the end block, use an
+ // identity mapping of CPI's to CPE's.
+ const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants();
+
+ const DataLayout &TD = MF->getDataLayout();
+ for (unsigned i = 0, e = CPs.size(); i != e; ++i) {
+ unsigned Size = CPs[i].getSizeInBytes(TD);
+ Align Alignment = CPs[i].getAlign();
+ // Verify that all constant pool entries are a multiple of their alignment.
+ // If not, we would have to pad them out so that instructions stay aligned.
+ assert(isAligned(Alignment, Size) && "CP Entry not multiple of 4 bytes!");
+
+ // Insert CONSTPOOL_ENTRY before entries with a smaller alignment.
+ unsigned LogAlign = Log2(Alignment);
+ MachineBasicBlock::iterator InsAt = InsPoint[LogAlign];
+ MachineInstr *CPEMI =
+ BuildMI(*BB, InsAt, DebugLoc(), TII->get(SH::CONSTPOOL_ENTRY))
+ .addImm(i).addConstantPoolIndex(i).addImm(Size);
+ CPEMIs.push_back(CPEMI);
+
+ // Ensure that future entries with higher alignment get inserted before
+ // CPEMI. This is bucket sort with iterators.
+ for (unsigned a = LogAlign + 1; a <= MaxLogAlign; ++a)
+ if (InsPoint[a] == InsAt)
+ InsPoint[a] = CPEMI;
+
+ // Add a new CPEntry, but no corresponding CPUser yet.
+ CPEntries.emplace_back(1, CPEntry(CPEMI, i));
+ LLVM_DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = "
+ << Size << ", align = " << Alignment.value() << '\n');
+ }
+ LLVM_DEBUG(BB->dump());
+}
+
+/// fixupImmediateBr - Fix up an immediate branch whose destination is too far
+/// away to fit in its displacement field.
+bool SuperHConstantIslands::fixupImmediateBr(ImmBranch &Br) {
+ MachineInstr *MI = Br.MI;
+ MachineBasicBlock *MBB = MI->getParent();
+ MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
+
+ // Check to see if the DestBB is already in-range.
+ if (BBUtils->isBBInRange(MI, DestBB, Br.MaxDisp))
+ return false;
+
+ // Use BRA to implement far jump.
+ Br.MaxDisp = (1 << 11);
+ MI->setDesc(TII->get(SH::BRA));
+ BBInfoVector &BBInfo = BBUtils->getBBInfo();
+ BBInfo[MBB->getNumber()].Size += 2;
+ BBUtils->adjustBBOffsetsAfter(MBB);
+ return true;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// INITIALIZATION
+//===----------------------------------------------------------------------===//
+
+/// createARMConstantIslandPass - returns an instance of the constpool
+/// island pass.
+FunctionPass *llvm::createSuperHConstantIslandPass() {
+ return new SuperHConstantIslands();
+}
+
+
+INITIALIZE_PASS(SuperHConstantIslands, "sh-cp-islands", SH_CP_ISLANDS_OPT_NAME,
+ false, false)
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
new file mode 100644
index 0000000000000..0b9d5eaf0701d
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
@@ -0,0 +1,223 @@
+//===- SuperHConstantPoolValue.cpp - SuperH constantpool value --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SuperH specific constantpool value class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHConstantPoolValue.h"
+
+using namespace llvm;
+
+
+
+//===----------------------------------------------------------------------===//
+// SuperHConstantPoolValue
+//===----------------------------------------------------------------------===//
+
+SuperHConstantPoolValue::SuperHConstantPoolValue(Type *Ty, unsigned id,
+ SHCP::SHCPKind kind,
+ SHCP::SHCPModifier modifier)
+ : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind), Modifier(modifier) {}
+
+SuperHConstantPoolValue::SuperHConstantPoolValue(LLVMContext &C, unsigned id,
+ SHCP::SHCPKind kind,
+ SHCP::SHCPModifier modifier)
+ : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)),
+ LabelId(id), Kind(kind), Modifier(modifier) {}
+
+SuperHConstantPoolValue::~SuperHConstantPoolValue() = default;
+
+StringRef SuperHConstantPoolValue::getModifierText() const {
+ switch (Modifier) {
+ // FIXME: Are these case sensitive? It'd be nice to lower-case all the
+ // strings if that's legal.
+ case SHCP::no_modifier:
+ return "none";
+ case SHCP::GOT_PCREL:
+ return "GOT_PCREL";
+ case SHCP::GOT_PLTOFF:
+ return "gotpltoff";
+ case SHCP::DIR:
+ return "";
+ }
+ llvm_unreachable("Unknown modifier!");
+}
+
+int SuperHConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
+ Align Alignment) {
+ llvm_unreachable("Shouldn't be calling this directly!");
+}
+
+void
+SuperHConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
+ ID.AddInteger(LabelId);
+}
+
+bool
+SuperHConstantPoolValue::hasSameValue(SuperHConstantPoolValue *ACPV) {
+ if (ACPV->Kind == Kind &&
+ ACPV->Modifier == Modifier &&
+ ACPV->LabelId == LabelId) {
+
+ // Two PC relative constpool entries containing the same GV address or
+ // external symbols. FIXME: What about blockaddress?
+ if (Kind == SHCP::CPValue || Kind == SHCP::CPExtSymbol)
+ return true;
+ }
+ return false;
+}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void SuperHConstantPoolValue::dump() const {
+ errs() << " " << *this;
+}
+#endif
+
+void SuperHConstantPoolValue::print(raw_ostream &O) const {
+ if (Modifier) O << "(" << getModifierText() << ")";
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// SuperHConstantPoolConstant
+//===----------------------------------------------------------------------===//
+
+SuperHConstantPoolConstant::SuperHConstantPoolConstant(Type *Ty,
+ const Constant *C,
+ unsigned ID,
+ SHCP::SHCPKind Kind,
+ SHCP::SHCPModifier Modifier)
+ : SuperHConstantPoolValue(Ty, ID, Kind, Modifier),
+ CVal(C) {}
+
+SuperHConstantPoolConstant::SuperHConstantPoolConstant(const Constant *C,
+ unsigned ID,
+ SHCP::SHCPKind Kind,
+ SHCP::SHCPModifier Modifier)
+ : SuperHConstantPoolValue((Type*)C->getType(), ID, Kind, Modifier),
+ CVal(C) {}
+
+SuperHConstantPoolConstant::SuperHConstantPoolConstant(const GlobalVariable *GV,
+ const Constant *C)
+ : SuperHConstantPoolValue((Type *)C->getType(), 0, SHCP::CPPromotedGlobal,
+ SHCP::no_modifier), CVal(C) {
+ GVars.insert(GV);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID) {
+ return new SuperHConstantPoolConstant(C, ID, SHCP::CPValue,
+ SHCP::no_modifier);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const GlobalVariable *GVar,
+ const Constant *Initializer) {
+ return new SuperHConstantPoolConstant(GVar, Initializer);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const GlobalValue *GV,
+ SHCP::SHCPModifier Modifier) {
+ return new SuperHConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()),
+ GV, 0, SHCP::CPValue,
+ Modifier);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID,
+ SHCP::SHCPKind Kind) {
+ return new SuperHConstantPoolConstant(C, ID, Kind,
+ SHCP::no_modifier);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID,
+ SHCP::SHCPKind Kind,
+ SHCP::SHCPModifier Modifier) {
+ return new SuperHConstantPoolConstant(C, ID, Kind, Modifier);
+}
+
+const GlobalValue *SuperHConstantPoolConstant::getGV() const {
+ return dyn_cast_or_null<GlobalValue>(CVal);
+}
+
+const BlockAddress *SuperHConstantPoolConstant::getBlockAddress() const {
+ return dyn_cast_or_null<BlockAddress>(CVal);
+}
+
+int SuperHConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
+ Align Alignment) {
+ int index =
+ getExistingMachineCPValueImpl<SuperHConstantPoolConstant>(CP, Alignment);
+ if (index != -1) {
+ auto *CPV = static_cast<SuperHConstantPoolValue*>(
+ CP->getConstants()[index].Val.MachineCPVal);
+ auto *Constant = cast<SuperHConstantPoolConstant>(CPV);
+ Constant->GVars.insert_range(GVars);
+ }
+ return index;
+}
+
+bool SuperHConstantPoolConstant::hasSameValue(SuperHConstantPoolValue *ACPV) {
+ const SuperHConstantPoolConstant *ACPC = dyn_cast<SuperHConstantPoolConstant>(ACPV);
+ return ACPC && ACPC->CVal == CVal && SuperHConstantPoolValue::hasSameValue(ACPV);
+}
+
+void SuperHConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
+ ID.AddPointer(CVal);
+ for (const auto *GV : GVars)
+ ID.AddPointer(GV);
+ SuperHConstantPoolValue::addSelectionDAGCSEId(ID);
+}
+
+void SuperHConstantPoolConstant::print(raw_ostream &O) const {
+ O << CVal->getName();
+ SuperHConstantPoolValue::print(O);
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// SuperHConstantPoolSymbol
+//===----------------------------------------------------------------------===//
+
+SuperHConstantPoolSymbol::SuperHConstantPoolSymbol(LLVMContext &C, StringRef s,
+ unsigned id,
+ SHCP::SHCPModifier Modifier)
+ : SuperHConstantPoolValue(C, id, SHCP::CPExtSymbol, Modifier),
+ S(std::string(s)) {}
+
+SuperHConstantPoolSymbol *SuperHConstantPoolSymbol::Create(LLVMContext &C,
+ StringRef s, unsigned ID) {
+ return new SuperHConstantPoolSymbol(C, s, ID, SHCP::no_modifier);
+}
+
+int SuperHConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
+ Align Alignment) {
+ return getExistingMachineCPValueImpl<SuperHConstantPoolSymbol>(CP, Alignment);
+}
+
+bool SuperHConstantPoolSymbol::hasSameValue(SuperHConstantPoolValue *SCPV) {
+ const SuperHConstantPoolSymbol *ACPS = dyn_cast<SuperHConstantPoolSymbol>(SCPV);
+ return ACPS && ACPS->S == S && SuperHConstantPoolValue::hasSameValue(SCPV);
+}
+
+void SuperHConstantPoolSymbol::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
+ ID.AddString(S);
+ SuperHConstantPoolValue::addSelectionDAGCSEId(ID);
+}
+
+void SuperHConstantPoolSymbol::print(raw_ostream &O) const {
+ O << S;
+ SuperHConstantPoolValue::print(O);
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
new file mode 100644
index 0000000000000..f606b1b6869b5
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
@@ -0,0 +1,212 @@
+//===- SuperHConstantPoolValue.h - SuperH constantpool value ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SuperH specific constantpool value class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHCONSTANTPOOLVALUE_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHCONSTANTPOOLVALUE_H
+
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/MC/MCSymbol.h"
+
+namespace llvm {
+
+class BlockAddress;
+class Constant;
+class GlobalValue;
+class GlobalVariable;
+class LLVMContext;
+class MachineBasicBlock;
+class raw_ostream;
+class Type;
+
+namespace SHCP {
+
+ enum SHCPKind {
+ CPValue,
+ CPExtSymbol,
+ CPBlockAddress,
+ CPMachineBasicBlock,
+ CPPromotedGlobal
+ };
+
+ enum SHCPModifier {
+ no_modifier, /// None
+ DIR, /// Direct
+ GOT_PCREL, /// Global Offset Table, PC Relative
+ GOT_PLTOFF, /// Global Offset Table, Thread Pointer Offset
+ };
+
+} // end namespace SHCP
+
+class SuperHConstantPoolValue : public MachineConstantPoolValue {
+ unsigned LabelId; // Label id of the load.
+ SHCP::SHCPKind Kind; // Kind of constant.
+ SHCP::SHCPModifier Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8))
+protected:
+ SuperHConstantPoolValue(Type *Ty, unsigned id, SHCP::SHCPKind Kind,
+ SHCP::SHCPModifier Modifier);
+
+ SuperHConstantPoolValue(LLVMContext &C, unsigned id, SHCP::SHCPKind Kind,
+ SHCP::SHCPModifier Modifier);
+
+ template <typename Derived>
+ int getExistingMachineCPValueImpl(MachineConstantPool *CP, Align Alignment) {
+ const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
+ for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
+ if (Constants[i].isMachineConstantPoolEntry() &&
+ Constants[i].getAlign() >= Alignment) {
+ auto *CPV =
+ static_cast<SuperHConstantPoolValue*>(Constants[i].Val.MachineCPVal);
+ if (Derived *APC = dyn_cast<Derived>(CPV))
+ if (cast<Derived>(this)->equals(APC))
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+public:
+ ~SuperHConstantPoolValue() override;
+
+ SHCP::SHCPKind getKind() const { return Kind; }
+ SHCP::SHCPModifier getModifier() const { return Modifier; }
+ StringRef getModifierText() const;
+ bool hasModifier() const { return Modifier != SHCP::no_modifier; }
+
+ unsigned getLabelId() const { return LabelId; }
+
+ bool isGlobalValue() const { return Kind == SHCP::CPValue; }
+ bool isExtSymbol() const { return Kind == SHCP::CPExtSymbol; }
+ bool isBlockAddress() const { return Kind == SHCP::CPBlockAddress; }
+ bool isMachineBasicBlock() const{ return Kind == SHCP::CPMachineBasicBlock; }
+ bool isPromotedGlobal() const{ return Kind == SHCP::CPPromotedGlobal; }
+
+ int getExistingMachineCPValue(MachineConstantPool *CP,
+ Align Alignment) override;
+
+ void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
+
+ /// hasSameValue - Return true if this ARM constpool value can share the same
+ /// constantpool entry as another ARM constpool value.
+ virtual bool hasSameValue(SuperHConstantPoolValue *ACPV);
+
+ bool equals(const SuperHConstantPoolValue *A) const {
+ return this->LabelId == A->LabelId &&
+ this->Modifier == A->Modifier;
+ }
+
+ void print(raw_ostream &O) const override;
+ void print(raw_ostream *O) const { if (O) print(*O); }
+ void dump() const;
+};
+
+inline raw_ostream &operator<<(raw_ostream &O, const SuperHConstantPoolValue &V) {
+ V.print(O);
+ return O;
+}
+
+
+/// SuperHConstantPoolConstant - SuperH-specific constant pool values for Constants,
+/// Functions, and BlockAddresses.
+class SuperHConstantPoolConstant : public SuperHConstantPoolValue {
+ const Constant *CVal; // Constant being loaded.
+ SmallPtrSet<const GlobalVariable*, 1> GVars;
+
+ SuperHConstantPoolConstant(const Constant *C,
+ unsigned ID,
+ SHCP::SHCPKind Kind,
+ SHCP::SHCPModifier Modifier);
+ SuperHConstantPoolConstant(Type *Ty, const Constant *C,
+ unsigned ID,
+ SHCP::SHCPKind Kind,
+ SHCP::SHCPModifier Modifier);
+ SuperHConstantPoolConstant(const GlobalVariable *GV, const Constant *Init);
+
+public:
+ static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID);
+ static SuperHConstantPoolConstant *Create(const GlobalValue *GV,
+ SHCP::SHCPModifier Modifier);
+ static SuperHConstantPoolConstant *Create(const GlobalVariable *GV,
+ const Constant *Initializer);
+ static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID,
+ SHCP::SHCPKind Kind);
+ static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID,
+ SHCP::SHCPKind Kind,
+ SHCP::SHCPModifier Modifier);
+
+ const GlobalValue *getGV() const;
+ const BlockAddress *getBlockAddress() const;
+
+ using promoted_iterator = SmallPtrSet<const GlobalVariable *, 1>::iterator;
+
+ iterator_range<promoted_iterator> promotedGlobals() { return GVars; }
+
+ const Constant *getPromotedGlobalInit() const {
+ return CVal;
+ }
+
+ int getExistingMachineCPValue(MachineConstantPool *CP,
+ Align Alignment) override;
+
+ /// hasSameValue - Return true if this ARM constpool value can share the same
+ /// constantpool entry as another ARM constpool value.
+ bool hasSameValue(SuperHConstantPoolValue *ACPV) override;
+
+ void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
+
+ void print(raw_ostream &O) const override;
+
+ static bool classof(const SuperHConstantPoolValue *APV) {
+ return APV->isGlobalValue() || APV->isBlockAddress() ||
+ APV->isPromotedGlobal();
+ }
+
+ bool equals(const SuperHConstantPoolConstant *A) const {
+ return CVal == A->CVal && SuperHConstantPoolValue::equals(A);
+ }
+};
+
+/// SuperHConstantPoolSymbol - SH-specific constantpool
+/// values for external symbols.
+class SuperHConstantPoolSymbol : public SuperHConstantPoolValue {
+ const std::string S; // ExtSymbol being loaded.
+
+ SuperHConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id, SHCP::SHCPModifier Modifier);
+
+public:
+ static SuperHConstantPoolSymbol *Create(LLVMContext &C, StringRef s, unsigned ID);
+
+ StringRef getSymbol() const { return S; }
+
+ int getExistingMachineCPValue(MachineConstantPool *CP,
+ Align Alignment) override;
+
+ void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
+
+ /// hasSameValue - Return true if this ARM constpool value can share the same
+ /// constantpool entry as another ARM constpool value.
+ bool hasSameValue(SuperHConstantPoolValue *SCPV) override;
+
+ void print(raw_ostream &O) const override;
+
+ static bool classof(const SuperHConstantPoolValue *SCPV) {
+ return SCPV->isExtSymbol();
+ }
+
+ bool equals(const SuperHConstantPoolSymbol *A) const {
+ return S == A->S && SuperHConstantPoolValue::equals(A);
+ }
+};
+
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 9f7bacb1c92b5..8d092e0b570aa 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -51,39 +51,91 @@ class SuperHFillDelaySlots : public MachineFunctionPass {
bool expandMI(Block &MBB, BlockIt MBBI);
// Expansion functions
+ MachineInstr *findSlotCandidate(Block &MBB, BlockIt MBBI);
bool fillDelaySlot(Block &MBB, BlockIt MBBI);
};
} // end namespace
-bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
+
+
+//===----------------------------------------------------------------------===//
+// Expansions
+//===----------------------------------------------------------------------===//
+
+// Walks backwards through the basic block to find a candidate that is eligible
+// for filling delay slots.
+MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
+
+
+ // TODO: Make this a while loop that keeps a list of "used" registers
+ // by instructions.
if (auto *Prev = MBBI->getPrevNode()) {
+ unsigned Opcode = Prev->getOpcode();
+
+ // If we encounter a branch instruction, then it's no longer safe to
+ // move the instruction down.
+ if (Prev->isBranch() || Prev->isCall() || Prev->isReturn())
+ return nullptr;
+
+ // NOTE: RTS has an extra constraint that it cannot have
+ // lds @r15+,PR or equivalent in its delay slot.
+ if (MI.isReturn()) {
+
+ // Skip the LDS instruction.
+ if (Opcode == SH::LDSLRminciPR || Opcode == SH::LDSRmPR)
+ return nullptr;
+ }
- // If the prior instruction is capable of filling the delay slot
- // swap the 2 instructions.
- if (TII->canFillDelaySlot(Prev->getOpcode())) {
- LDBG() << "Swapping " << TII->getName(MI.getOpcode())
- << " and " << TII->getName(Prev->getOpcode())
- << " @ " << MBB.getParent()->getName();
- MBB.insertAfter(MBBI, Prev->removeFromParent());
- return true;
+ // NOTE: Conditional branches can't have their condition code set
+ // in the delay slot. As such, if the previous instruction
+ // implicitly defines the status register, assume that the
+ // T bit was set.
+ if (MI.isConditionalBranch()) {
+ if (Prev->definesRegister(SH::SR, TRI))
+ return nullptr;
+ }
+
+ // Otherwise, select this instruction if can fill a delay slot,
+ // has no prior node, or the prior node is not a delay slot.
+ if (TII->canFillDelaySlot(Opcode)) {
+ if (!Prev->getPrevNode() || !Prev->getPrevNode()->hasDelaySlot())
+ return Prev;
}
}
- LDBG() << "Inserting NOP after " << TII->getName(MI.getOpcode())
- << " @ " << MBB.getParent()->getName();
+ return nullptr;
+}
+
+// Finds and fills delay slots of instructions in a basic block.
+bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
+ MachineFunction &MF = *MBB.getParent();
+ MachineInstr &MI = *MBBI;
+
+ if (auto *Candidate = SuperHFillDelaySlots::findSlotCandidate(MBB, MBBI)) {
+ LLVM_DEBUG(dbgs() << "Swapping " << TII->getName(MI.getOpcode())
+ << " and " << TII->getName(Candidate->getOpcode())
+ << " @ " << MBB.getParent()->getName() << "\n");
+
+ MBB.insertAfter(MBBI, Candidate->removeFromParent());
+ return true;
+ }
+
+ LLVM_DEBUG(dbgs() << "Inserting NOP after " << TII->getName(MI.getOpcode())
+ << " @ " << MBB.getParent()->getName() << "\n");
// Otherwise just insert a NOP.
- BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(SH::NOP));
+ MBB.insertAfter(MBBI, MF.CreateMachineInstr(TII->get(SH::NOP), MI.getDebugLoc()));
return true;
}
+
//===----------------------------------------------------------------------===//
-// HELPERS
+// Helpers
//===----------------------------------------------------------------------===//
bool SuperHFillDelaySlots::expandMI(Block &MBB, BlockIt MBBI) {
@@ -109,6 +161,8 @@ bool SuperHFillDelaySlots::expandMBB(Block &MBB) {
}
bool SuperHFillDelaySlots::runOnMachineFunction(MachineFunction &MF) {
+ LLVM_DEBUG(dbgs() << "\n********** SuperHFillDelaySlots **********\n");
+
bool Modified = false;
const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 4d11c6e99983c..93baa923182da 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -17,15 +17,22 @@
#include "SuperHInstrInfo.h"
#include "SuperHRegisterInfo.h"
#include "SuperHSubtarget.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCRegister.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugLog.h"
#include "llvm/Target/TargetMachine.h"
#define DEBUG_TYPE "sh-framelowering"
+static cl::opt<bool>
+AccumOutgoingArgs("sh-accumulate-outgoing-args", cl::Hidden, cl::init(false),
+ cl::desc("Reserve space for outgoing arguments in the function prologue."));
+
using namespace llvm;
// Get amount of times to shift the value in a SP adjustment
@@ -57,8 +64,8 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
// Fast path, emit a single immediate add.
// Emit add #-(size),r15
BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
- .addImm((int)AdjValue)
- .addReg(SP);
+ .addReg(SP)
+ .addImm((int)AdjValue);
return true;
}
@@ -106,51 +113,82 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
const SuperHInstrInfo &TII = *STI.getInstrInfo();
const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+ const MCContext &Ctx = MF.getContext();
DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
bool HasFP = hasFP(MF);
Register SP = RII.getStackRegister();
Register FP = RII.getFrameRegister();
+ Register GOT = RII.getGOTRegister();
- LDBG() << "emitPrologue";
+ // Early exit if we have no frame pointer.
+ if (!HasFP) {
+ return;
+ }
// Realign stack
uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
MFI.setStackSize(StackSize);
+
+ if (STI.isPositionIndependent()) {
+ // Position Independent Prologue
+
+ // 1. Store GOT to stack and load local GOT.
+ if (auto *GOTSym = MF.getPICBaseSymbol()) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+ .addReg(GOT)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+
+ // 2. Establish Stack Frame
+ // mov.l r14, at -r15
+ // add <stackadj>,r15
+ // mov r15,r14
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), FP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
+ emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), SP)
+ .addReg(FP)
+ .setMIFlag(MachineInstr::FrameSetup);
- // 1. Create stack frame
- emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
-
- // TODO: Create working register set.
+ // 4. Save return address to stack.
+ if (MFI.hasCalls()) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
- // 3. Save return address to stack.
- BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameSetup);
+ } else {
+ // Position Dependent Prologue
- // 4. Establish frame pointer
- if (HasFP) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
- .addReg(SP)
+ // 1. Establish Frame Pointer
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+ .addReg(FP)
.setMIFlag(MachineInstr::FrameSetup);
- }
- // TODO: Establish GCP?
+ // 2. Create new stack frame
+ emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
+
+ // 3. Save return address to stack.
+ if (MFI.hasCalls()) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+ }
}
void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
Register SP = RII.getStackRegister();
Register FP = RII.getFrameRegister();
-
- LDBG() << "emitEpilogue";
// Early exit if we have no frame pointer.
if (!hasFP(MF)) {
return;
}
-
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
MachineFrameInfo &MFI = MF.getFrameInfo();
DebugLoc DL = MBBI->getDebugLoc();
@@ -159,16 +197,79 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
uint32_t StackSize = MFI.getStackSize();
- // TODO: Restore callee save registers
+ if (STI.isPositionIndependent()) {
- // 2. Restore return address from stack
- BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameDestroy);
+ // 1. Restore return address from stack.
+ if (MFI.hasCalls()) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ }
+
+ // 2. Delete stack frame, restoring stack pointer.
+ if (StackSize > 0)
+ emitSPAdj(MF, MBB, MBBI, StackSize);
+
+ } else {
+
+ // 1. Restore return address from stack.
+ if (MFI.hasCalls()) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ }
- // 3. Delete stack frame, restoring stack pointer.
- if (StackSize > 0)
- emitSPAdj(MF, MBB, MBBI, StackSize);
+ // 2. Delete stack frame, restoring stack pointer.
+ if (StackSize > 0)
+ emitSPAdj(MF, MBB, MBBI, StackSize);
+ }
+}
+bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+
+ if (CSI.empty()) {
+ return false;
+ }
+
+ DebugLoc DL = MBB.findDebugLoc(MI);
+ MachineFunction &MF = *MBB.getParent();
+ const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+ const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+ const TargetInstrInfo &TII = *STI.getInstrInfo();
+ Register SP = RII.getStackRegister();
+
+ for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
+ MCRegister Reg = I.getReg();
+ BuildMI(MBB, MI, DL, TII.get(SH::MOVLRmRndeci), SP)
+ .addReg(Reg)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+
+ return true;
+}
+
+bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+
+ if (CSI.empty()) {
+ return false;
+ }
+
+ DebugLoc DL = MBB.findDebugLoc(MI);
+ MachineFunction &MF = *MBB.getParent();
+ const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+ const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+ const TargetInstrInfo &TII = *STI.getInstrInfo();
+ Register SP = RII.getStackRegister();
+
+ for (const CalleeSavedInfo &I : CSI) {
+ MCRegister Reg = I.getReg();
+ BuildMI(MBB, MI, DL, TII.get(SH::MOVLRminciRn), SP)
+ .addReg(Reg)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ }
+
+ return true;
}
MachineBasicBlock::iterator
@@ -178,8 +279,6 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
const SuperHInstrInfo &TII = *STI.getInstrInfo();
- LDBG() << "eliminateCallFramePseudoInstr";
-
// If call frame is reserved, erase.
if (hasReservedCallFrame(MF)) {
return MBB.erase(MI);
@@ -194,16 +293,21 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
DebugLoc DL = MI->getDebugLoc();
unsigned int Opcode = MI->getOpcode();
if (Opcode == TII.getCallFrameSetupOpcode()) {
- LDBG() << "eliminateCallFramePseudoInstr->CallFrameSetup";
+
} else {
- LDBG() << "eliminateCallFramePseudoInstr->CallFrameDestroy";
assert(Opcode == TII.getCallFrameDestroyOpcode());
-
}
return MBB.erase(MI);
}
+bool SuperHFrameLowering::canSimplifyCallFramePseudos(
+ const MachineFunction &MF) const {
+ // Always simplify call frame pseudo instructions, even when
+ // hasReservedCallFrame is false.
+ return true;
+}
+
bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index dd2cc63aaa32e..7a20234e7817c 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -31,11 +31,16 @@ class SuperHFrameLowering : public TargetFrameLowering {
/*LocalAreaOffset*/0,
/*TransAl*/Align(4)),
STI(STI) {}
+ bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
+ bool hasReservedCallFrame(const MachineFunction &MF) const override;
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
-
- bool hasReservedCallFrame(const MachineFunction &MF) const override;
+ bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
+ bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
+
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const override;
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index badd48f1df62a..3b9e745b8d334 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -11,7 +11,11 @@
//
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/SuperHBaseInfo.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
#include "SuperH.h"
+#include "SuperHConstantPoolValue.h"
+#include "SuperHMachineFunctionInfo.h"
#include "SuperHSubtarget.h"
#include "SuperHTargetMachine.h"
#include "SuperHSelectionDAGInfo.h"
@@ -19,15 +23,45 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/DebugLog.h"
#define DEBUG_TYPE "sh-isel"
#define PASS_NAME "SH DAG->DAG Instruction Selection"
+static cl::opt<bool>
+CBranchForceDelaySlot("sh-cbranch-force-delay-slot", cl::Hidden, cl::init(false),
+ cl::desc("Force the usage of delay slots for conditional branches."));
+
using namespace llvm;
namespace {
+struct SHAddressWrapper {
+ enum SHAddrType {
+ GLOBAL_VALUE,
+ CONSTANT,
+ BLOCK,
+ SYM_LOCAL,
+ SYM_EXTERNAL,
+ };
+ SHAddrType Type;
+ SDValue BaseReg;
+ int64_t Disp;
+
+ // Max size of displacement.
+ unsigned DispSize;
+
+ const GlobalValue *GV;
+ const Constant *CP;
+ const BlockAddress *BlockAddr;
+ const char *ES;
+ MCSymbol *MCSym;
+ SHRefClass SymbolFlags; // SHII::MO_*
+
+ SHAddressWrapper(unsigned DS) : DispSize(DS) { }
+};
+
/// Lowers LLVM IR (in DAG form) to SuperH MC instructions (in DAG form).
class SuperHDAGToDAGISel : public SelectionDAGISel {
public:
@@ -40,7 +74,26 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
InlineAsm::ConstraintCode ConstraintCode,
std::vector<SDValue> &OutOps) override;
- bool SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValue Rhs);
+
+ bool SelectAddr(SDNode *Root, SDValue N, SDValue &Base, SDValue &Disp);
+
+
+ /// Return a target constant with the specified value of type i4.
+ inline SDValue getI4Imm(int64_t Imm, const SDLoc &DL) {
+ return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i4);
+ }
+
+
+ /// Return a target constant with the specified value of type i8.
+ inline SDValue getI8Imm(int64_t Imm, const SDLoc &DL) {
+ return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i8);
+ }
+
+
+ /// Return a target constant with the specified value of type i16.
+ inline SDValue getI16Imm(int64_t Imm, const SDLoc &DL) {
+ return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i16);
+ }
// Include the pieces autogenerated from the target description.
#include "SuperHGenDAGISel.inc"
@@ -49,10 +102,13 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
void Select(SDNode *N) override;
bool trySelect(SDNode *N);
- bool trySelectRET(SDNode *N);
bool trySelectSDIV(SDNode *N);
bool trySelectUDIV(SDNode *N);
bool trySelectFrameIndex(SDNode *N);
+ bool trySelectWrapper(SDNode *N);
+ bool trySelectCMP(SDNode *N);
+ bool trySelectBrcond(SDNode *N);
+ bool trySelectSELECT_CC(SDNode *N);
const SuperHSubtarget *Subtarget;
};
@@ -81,11 +137,158 @@ bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
}
+
+
//===----------------------------------------------------------------------===//
-// Address Lowering
+// Address Lowering
//===----------------------------------------------------------------------===//
-bool SuperHDAGToDAGISel::SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValue Rhs) {
+bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
+ auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
+ auto DL = SDLoc(N);
+
+ MachineFunction &MF = CurDAG->getMachineFunction();
+ SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+ SDValue N0 = N->getOperand(0);
+
+ // Global Addresses
+ if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+ ReplaceNode(N, Res);
+ return true;
+ }
+
+ // External Symbols
+ if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+ ReplaceNode(N, Res);
+ return true;
+ }
+
+ // Block Addresses
+ if (auto *CPV = SFI->tryGetConstant((BlockAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+ ReplaceNode(N, Res);
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Conditionals Lowering
+//===----------------------------------------------------------------------===//
+
+bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ SDLoc DL(N);
+
+ // NOTE: The comparisons just set the T bit, it's up to later instructions
+ // to interpret the T bit as positive or negative.
+ SDNode *Res = nullptr;
+ switch(CC) {
+ default: break;
+ case ISD::SETEQ:
+ case ISD::SETNE: {
+
+ // TST would be faster in this case.
+ if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
+ if (C->getSExtValue() == 0) {
+ Res = CurDAG->getMachineNode(SH::TSTRmRn, DL, MVT::i32, LHS, LHS);
+ break;
+ }
+ }
+ Res = CurDAG->getMachineNode(SH::CMPEQRmRn, DL, MVT::i32, LHS, RHS);
+ break;
+ }
+ case ISD::SETUGE:
+ case ISD::SETULT: {
+ Res = CurDAG->getMachineNode(SH::CMPHSRmRn, DL, MVT::i32, LHS, RHS);
+ break;
+ }
+ case ISD::SETOGE:
+ case ISD::SETOLT: {
+ Res = CurDAG->getMachineNode(SH::CMPGERmRn, DL, MVT::i32, LHS, RHS);
+ break;
+ }
+ case ISD::SETUGT:
+ case ISD::SETULE: {
+ Res = CurDAG->getMachineNode(SH::CMPGTRmRn, DL, MVT::i32, LHS, RHS);
+ break;
+ }
+ case ISD::SETOGT:
+ case ISD::SETOLE: {
+ Res = CurDAG->getMachineNode(SH::CMPHIRmRn, DL, MVT::i32, LHS, RHS);
+ break;
+ }
+ }
+
+ if (Res) {
+ ReplaceUses(SDValue(N, 0), SDValue(Res, 0));
+ CurDAG->RemoveDeadNode(N);
+ return true;
+ }
+
+ return false;
+}
+
+bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
+ SDValue Chain = N->getOperand(0);
+ SDValue Dest = N->getOperand(1);
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ SDValue Cmp = N->getOperand(3);
+ SDLoc DL(N);
+
+ // NOTE: The CMP instruction writes implicitly to the T bit of the status
+ // register, as such, we need to add said copy to our chain to ensure
+ // scheduling can handle it.
+ Chain = CurDAG->getCopyToReg(Chain, DL, SH::SR, Cmp, SDValue());
+
+ // NOTE: The comparisons just set the T bit, it's up to later instructions
+ // to interpret the T bit as positive or negative.
+ MachineSDNode *Res = nullptr;
+ switch(CC) {
+ default: break;
+ case ISD::SETEQ:
+ case ISD::SETUGE:
+ case ISD::SETOGE:
+ case ISD::SETUGT:
+ case ISD::SETOGT:
+ Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BTS : SH::BT,
+ DL, MVT::Other, Dest, Chain);
+ break;
+ case ISD::SETNE:
+ case ISD::SETULE:
+ case ISD::SETOLE:
+ case ISD::SETULT:
+ case ISD::SETOLT:
+ Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BFS : SH::BF,
+ DL, MVT::Other, Dest, Chain);
+ break;
+ }
+
+ if (Res) {
+ ReplaceUses(SDValue(N, 0), SDValue(Res, 0));
+ CurDAG->RemoveDeadNode(N);
+ return true;
+ }
+
+ return false;
+}
+
+bool SuperHDAGToDAGISel::trySelectSELECT_CC(SDNode *N) {
+ const SDValue &TrueV = N->getOperand(0);
+ const SDValue &FalseV = N->getOperand(1);
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ const SDValue &Cmp = N->getOperand(3);
return false;
}
@@ -107,20 +310,48 @@ bool SuperHDAGToDAGISel::trySelectFrameIndex(SDNode *N) {
return true;
}
+
+
+
+//===----------------------------------------------------------------------===//
+// Selection Code
+//===----------------------------------------------------------------------===//
+
bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
unsigned Opcode = N->getOpcode();
+ SDLoc DL(N);
+
switch(Opcode) {
+ case ISD::GLOBAL_OFFSET_TABLE: {
+ SDValue GOT = CurDAG->getTargetExternalSymbol(
+ "_GLOBAL_OFFSET_TABLE_", MVT::i32, SHII::MO_GOTPC);
+ MachineSDNode *Res =
+ CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, GOT);
+ ReplaceNode(N, Res);
+ return true;
+ }
case ISD::FrameIndex:
return trySelectFrameIndex(N);
+ case SHISD::WRAPPER:
+ return trySelectWrapper(N);
+ case SHISD::CMP:
+ return trySelectCMP(N);
+ case SHISD::SELECT_CC:
+ return trySelectSELECT_CC(N);
+ case SHISD::BRCOND:
+ return trySelectBrcond(N);
default:
return false;
}
}
void SuperHDAGToDAGISel::Select(SDNode *N) {
+
+ LLVM_DEBUG(dbgs() << "SH: Selecting "; N->dump(CurDAG); dbgs() << '\n');
// Node was already selected?
if (N->isMachineOpcode()) {
+ LLVM_DEBUG(dbgs() << "== "; N->dump(CurDAG); dbgs() << '\n');
N->setNodeId(-1);
return;
}
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 39304e493a23d..59b297b48f886 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -12,23 +12,31 @@
//===-----------------------------------------------------------------------===//
#include "SuperHISelLowering.h"
+#include "SuperHConstantPoolValue.h"
+#include "SuperHMachineFunctionInfo.h"
#include "SuperHSelectionDAGInfo.h"
#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
#include "SuperHRegisterInfo.h"
+#include "SuperHSubtarget.h"
#include "SuperHTargetMachine.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/DebugLog.h"
using namespace llvm;
#define DEBUG_TYPE "sh-lower"
+#define DEBUG_FN_PRINT() LDBG() << __PRETTY_FUNCTION__;
+
static bool RetCC_SuperH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
@@ -47,12 +55,15 @@ static bool RetCC_SuperH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
const SuperHSubtarget &STI)
: TargetLowering(TM, STI), Subtarget(&STI) {
+ auto *RegInfo = Subtarget->getRegisterInfo();
// GPR Registers are always 32 bit on SuperH.
addRegisterClass(MVT::i32, &SH::GPRRegClass);
+ computeRegisterProperties(Subtarget->getRegisterInfo());
+
setSchedulingPreference(Sched::RegPressure);
setSupportsUnalignedAtomics(false);
- computeRegisterProperties(Subtarget->getRegisterInfo());
+ setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
// Loads and stores are legal
for (MVT VT : MVT::integer_valuetypes()) {
@@ -72,14 +83,154 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SREM, VT, Custom);
}
+ setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
+ setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
+ setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
+ setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
+
+
+ setOperationAction(ISD::BR_CC, MVT::i8, Custom);
+ setOperationAction(ISD::BR_CC, MVT::i16, Custom);
+ setOperationAction(ISD::BR_CC, MVT::i32, Custom);
+ setOperationAction(ISD::BR_CC, MVT::i64, Custom);
+ setOperationAction(ISD::BRCOND, MVT::Other, Expand);
+
+ setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
+ setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
+ setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
+ setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
+ setOperationAction(ISD::SETCC, MVT::i8, Custom);
+ setOperationAction(ISD::SETCC, MVT::i16, Custom);
+ setOperationAction(ISD::SETCC, MVT::i32, Custom);
+ setOperationAction(ISD::SETCC, MVT::i64, Custom);
setBooleanContents(ZeroOrOneBooleanContent);
setBooleanVectorContents(ZeroOrOneBooleanContent);
- setStackPointerRegisterToSaveRestore(SH::GBR);
- setJumpIsExpensive(true);
+ setJumpIsExpensive(false);
setMinFunctionAlignment(Align(4));
}
+
+
+
+//===----------------------------------------------------------------------===//
+// CONDITIONAL BRANCH LOWERING
+//===----------------------------------------------------------------------===//
+SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
+ SDValue &OutCC, SelectionDAG &DAG, SDLoc DL) const {
+ OutCC = DAG.getCondCode(CC);
+ return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, OutCC);
+}
+
+SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ SDValue TrueV = Op.getOperand(2);
+ SDValue FalseV = Op.getOperand(3);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
+ SDLoc DL(Op);
+
+ SDValue TargetCC;
+ SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+
+ SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
+ return DAG.getNode(SHISD::SELECT_CC, DL, Op.getValueType(), Ops);
+
+}
+
+SDValue SuperHTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
+ SDLoc DL(Op);
+
+ SDValue TargetCC;
+ SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+
+ SDValue TrueV = DAG.getConstant(1, DL, Op.getValueType());
+ SDValue FalseV = DAG.getConstant(0, DL, Op.getValueType());
+ SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
+ return DAG.getNode(SHISD::SELECT_CC, DL, Op.getValueType(), Ops);
+}
+
+SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
+ DEBUG_FN_PRINT()
+
+ SDValue Chain = Op.getOperand(0);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
+ SDValue LHS = Op.getOperand(2);
+ SDValue RHS = Op.getOperand(3);
+ SDValue Dest = Op.getOperand(4);
+ SDLoc DL(Op);
+
+ SDValue TargetCC;
+ SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+ return DAG.getNode(SHISD::BRCOND, DL, MVT::Other, Chain, Dest, TargetCC, Cmp);
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// ADDRESS LOWERING
+//===----------------------------------------------------------------------===//
+
+SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const {
+ DEBUG_FN_PRINT()
+
+ // Get the address of the target into a register
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Op)) {
+ auto PtrVT = getPointerTy(DAG.getDataLayout());
+ auto DL = SDLoc(G);
+
+ SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
+ SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, OpFlags);
+ return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
+ }
+ return SDValue();
+}
+
+SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const {
+ DEBUG_FN_PRINT()
+
+ // Get the address of the target into a register
+ if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Op)) {
+ auto PtrVT = getPointerTy(DAG.getDataLayout());
+ auto DL = SDLoc(S);
+
+ const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
+ SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
+
+ SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags);
+ return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
+ }
+ return SDValue();
+}
+
+SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
+ DEBUG_FN_PRINT()
+
+ // Get the address of the target into a register
+ if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) {
+ auto PtrVT = getPointerTy(DAG.getDataLayout());
+ auto DL = SDLoc(BA);
+
+ const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
+ SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
+
+ SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT, OpFlags);
+ return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
+ }
+ return SDValue();
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// ARGUMENT LOWERING
+//===----------------------------------------------------------------------===//
+
SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
@@ -158,6 +309,7 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
+
//===----------------------------------------------------------------------===//
// RETURN LOWERING
//===----------------------------------------------------------------------===//
@@ -209,6 +361,12 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
return DAG.getNode(SHISD::RET_GLUE, dl, MVT::Other, RetOps);
}
+SDValue SuperHTargetLowering::getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const {
+ return DAG.getRegister(Subtarget->getRegisterInfo()->getGOTRegister(),
+ getPointerTy(DAG.getDataLayout()));
+}
+
+
@@ -217,6 +375,7 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
//===----------------------------------------------------------------------===//
SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const {
+ const SuperHRegisterInfo &RI = *Subtarget->getRegisterInfo();
SelectionDAG &DAG = CLI.DAG;
MachineFunction &MF = DAG.getMachineFunction();
SDLoc &DL = CLI.DL;
@@ -225,40 +384,24 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
SDValue Chain = CLI.Chain;
SDValue Callee = CLI.Callee;
- bool &isTailCall = CLI.IsTailCall;
+ bool &IsTailCall = CLI.IsTailCall;
CallingConv::ID CallConv = CLI.CallConv;
- bool isVarArg = CLI.IsVarArg;
+ bool IsVarArg = CLI.IsVarArg;
// TODO: This was all yoinked from AVR, it likely needs to be modified to fit the calling
// convention of SuperH.
// Tail Call Optimisation not supported yet.
- isTailCall = false;
- isVarArg = false;
-
- // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
- // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
- // node so that legalize doesn't hack it.
- const Function *F = nullptr;
- if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- const GlobalValue *GV = G->getGlobal();
- if (isa<Function>(GV))
- F = cast<Function>(GV);
- Callee =
- DAG.getTargetGlobalAddress(GV, DL, getPointerTy(DAG.getDataLayout()));
- } else if (const ExternalSymbolSDNode *ES =
- dyn_cast<ExternalSymbolSDNode>(Callee)) {
- Callee = DAG.getTargetExternalSymbol(ES->getSymbol(),
- getPointerTy(DAG.getDataLayout()));
- }
+ IsTailCall = false;
+ IsVarArg = false;
- if (isVarArg) {
+ if (IsVarArg) {
return Chain;
}
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
+ CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
*DAG.getContext());
// Get a count of how many bytes are to be pushed on the stack.
@@ -324,8 +467,15 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
InGlue = Chain.getValue(1);
}
+ // Resolve the global value to jump to.
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+ Callee = LowerGlobalAddress(SDValue(G, 0), DAG);
+ } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
+ Callee = LowerExternalSymbol(SDValue(S, 0), DAG);
+ }
+ InGlue = Chain.getValue(1);
+
// Returns a chain & a flag for retval copy to use.
- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
SmallVector<SDValue, 8> Ops;
Ops.push_back(Chain);
Ops.push_back(Callee);
@@ -336,10 +486,6 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
}
- // The zero register (usually R1) must be passed as an implicit register so
- // that this register is correctly zeroed in interrupts.
- Ops.push_back(DAG.getRegister(SH::R0, MVT::i32));
-
// Add a register mask operand representing the call-preserved registers.
const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
const uint32_t *Mask =
@@ -351,7 +497,7 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
Ops.push_back(InGlue);
}
- Chain = DAG.getNode(SHISD::CALL, DL, NodeTys, Ops);
+ Chain = DAG.getNode(SHISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
InGlue = Chain.getValue(1);
// Create the CALLSEQ_END node.
@@ -361,17 +507,17 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
InGlue = Chain.getValue(1);
}
- return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, DL, DAG, InVals);
+ return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG, InVals);
}
SDValue SuperHTargetLowering::LowerCallResult(
- SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
+ SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
- CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
+ CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
*DAG.getContext());
// Handle runtime calling convs.
@@ -465,6 +611,18 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
case ISD::UDIV:
case ISD::SDIV:
return LowerDiv(Op, DAG);
+ case ISD::GlobalAddress:
+ return LowerGlobalAddress(Op, DAG);
+ case ISD::ExternalSymbol:
+ return LowerExternalSymbol(Op, DAG);
+ case ISD::BlockAddress:
+ return LowerBlockAddress(Op, DAG);
+ case ISD::SETCC:
+ return LowerBR_CC(Op, DAG);
+ case ISD::SELECT_CC:
+ return LowerBR_CC(Op, DAG);
+ case ISD::BR_CC:
+ return LowerBR_CC(Op, DAG);
}
return SDValue();
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index e23143b989fe5..ffdc90b53afc1 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -15,14 +15,34 @@
#define LLVM_LIB_TARGET_SUPERH_SUPERHISELLOWERING_H
#include "SuperH.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
namespace llvm {
class SuperHSubtarget;
+class MachineConstantPool;
class SuperHTargetLowering : public TargetLowering {
const SuperHSubtarget *Subtarget;
+public:
+ SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
+
+ // LowerToConstantPool - SuperH's compressed instruction set means that
+ // immediates and displacements can not be larger than 8 bits.
+ // As such we need to store said immediates and displacements within
+ // constants that are within range of the program counter.
+ //
+ // As such this function is a helper that:
+ // 1. Allocates a constant pool slot for the address
+ // 2. Inserts the target address into said slot.
+ // 3. Returns the neccesary, but non-legalized instruction sequence to fetch
+ // the address from that constant pool slot.
+ template<class NodeTy>
+ SDValue LowerToConstantPool(NodeTy* N, SelectionDAG &DAG) const;
+
SDValue LowerFormalArguments(SDValue Chain,
CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
@@ -40,15 +60,27 @@ class SuperHTargetLowering : public TargetLowering {
SmallVectorImpl<SDValue> &/*InVals*/) const override;
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
-
- // Custom Lowerings
+
+ // Lowerings
+ SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerDiv(SDValue Op, SelectionDAG &DAG) const;
+
+ SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
+ SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &OutCC,
+ SelectionDAG &DAG, SDLoc DL) const;
+private:
+
+ SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override;
+
+ // Lowerings
SDValue LowerCallResult(
SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const;
-public:
- SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
};
} // namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index b5015c9e8dc63..07523d475b3c5 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -15,14 +15,21 @@
#include "SuperHRegisterInfo.h"
#include "SuperHSubtarget.h"
#include "SuperHTargetMachine.h"
+#include "MCTargetDesc/SuperHInstPrinter.h"
#include "SuperH.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
using namespace llvm;
@@ -35,32 +42,200 @@ SuperHInstrInfo::SuperHInstrInfo(const SuperHSubtarget &ST)
: SuperHGenInstrInfo(ST, RI, SH::ADJCALLSTACKDOWN, SH::ADJCALLSTACKUP),
RI(ST), Subtarget(ST) { }
+
+
+// Gets whether a given opcode can fill a delay slot.
+//
+// SuperH does not allow branch instructions of any kind to be situated
+// in a delay slot, nor does it allow instructions with delay slots
+// to be chained together.
+bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
+ auto Desc = this->get(Opcode);
+ return !Desc.hasDelaySlot() &&
+ !Desc.isBranch() &&
+ !Desc.isCall() && !Desc.isReturn() &&
+ !(Desc.TSFlags & 0x1);
+}
+
+/// Return the noop instruction to use for a noop.
+MCInst SuperHInstrInfo::getNop() const {
+ MCInst I = MCInst();
+ I.setOpcode(SH::NOP);
+ return I;
+}
+
+void SuperHInstrInfo::insertNoop(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI) const {
+ BuildMI(&MBB, MI->getDebugLoc(), get(SH::NOP));
+}
+
+ISD::CondCode SuperHInstrInfo::getCondFromBranchOp(unsigned Op) const {
+ switch (Op) {
+ default:
+ return ISD::SETFALSE;
+ case SH::BRA:
+ case SH::NOP:
+ return ISD::SETTRUE;
+ case SH::BT:
+ case SH::BTS:
+ return ISD::SETEQ;
+ case SH::BF:
+ case SH::BFS:
+ return ISD::SETNE;
+ }
+}
+
+const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
+ switch (CC) {
+ default:
+ llvm_unreachable("Unknown condition code!");
+ case ISD::SETEQ:
+ case ISD::SETGE:
+ case ISD::SETGT:
+ return get(SH::BT);
+ case ISD::SETNE:
+ case ISD::SETLE:
+ case ISD::SETLT:
+ return get(SH::BF);
+ }
+}
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Stack Frames
+//===----------------------------------------------------------------------===//
+
void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, const DebugLoc &DL,
Register DestReg, Register SrcReg, bool KillSrc,
bool RenamableDest,
bool RenamableSrc) const {
+ // Do nothing, self copy.
+ if (SrcReg == DestReg)
+ return;
+
// If the targets are GPR registers, use MOV Rm, Rn.
if (SH::GPRRegClass.contains(DestReg, SrcReg)) {
BuildMI(MBB, MI, DL, get(SH::MOVRmRn), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
return;
- }
+ };
// Otherwise this is not possible.
llvm_unreachable("Impossible reg-to-reg copy");
}
-// Gets whether a given opcode can fill a delay slot.
-//
-// SuperH does not allow branch instructions of any kind to be situated
-// in a delay slot, nor does it allow instructions with delay slots
-// to be chained together.
-bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
- auto Desc = this->get(Opcode);
- return !Desc.hasDelaySlot() &&
- !Desc.isBranch() &&
- !Desc.isCall() && !Desc.isReturn() &&
- !(Desc.TSFlags & 0x1);
-}
\ No newline at end of file
+
+
+
+//===----------------------------------------------------------------------===//
+// Branch Analysis
+//===----------------------------------------------------------------------===//
+
+bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const {
+ // Start from the bottom of the block and work up, examining the
+ // terminator instructions.
+ MachineBasicBlock::iterator I = MBB.end();
+ MachineBasicBlock::iterator UnCondBrIter = MBB.end();
+
+ while (I != MBB.begin()) {
+ --I;
+ if (I->isDebugInstr()) {
+ continue;
+ }
+
+ LLVM_DEBUG(dbgs() << "analyzeBranch " << getName(I->getOpcode()) << "\n");
+
+ // Working from the bottom, when we see a non-terminator
+ // instruction, we're done.
+ if (!isUnpredicatedTerminator(*I)) {
+ break;
+ }
+
+ // Handle unconditional branches.
+ if (I->getOpcode() == SH::BRA) {
+ UnCondBrIter = I;
+
+ if (!AllowModify) {
+ TBB = I->getOperand(0).getMBB();
+ continue;
+ }
+
+ // If the block has any instructions after a BRA, delete them.
+ MBB.erase(std::next(I), MBB.end());
+ Cond.clear();
+ FBB = nullptr;
+
+ // Delete the BRA if it's equivalent to a fall-through.
+ if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
+ TBB = nullptr;
+ I->eraseFromParent();
+ I = MBB.end();
+ UnCondBrIter = MBB.end();
+ continue;
+ }
+
+ // TBB is used to indicate the unconditinal destination.
+ TBB = I->getOperand(0).getMBB();
+ continue;
+ }
+ }
+
+ return false;
+}
+
+unsigned SuperHInstrInfo::insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
+ const DebugLoc &DL,
+ int *BytesAdded) const {
+ return 0;
+}
+
+unsigned SuperHInstrInfo::removeBranch(MachineBasicBlock &MBB,
+ int *BytesRemoved) const {
+ return 0;
+}
+
+bool
+SuperHInstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+
+}
+
+MachineBasicBlock *SuperHInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
+ if (MI.isBranch())
+ return MI.getOperand(0).getMBB();
+
+ llvm_unreachable("unimplemented branch instructions");
+}
+
+bool SuperHInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
+ int64_t BrOffset) const {
+ switch (BranchOp) {
+ default:
+ llvm_unreachable("unexpected opcode!");
+ case SH::BF:
+ case SH::BT:
+ case SH::BFS:
+ case SH::BTS:
+ case SH::BRA:
+ return isIntN(8, BrOffset);
+ case SH::BSR:
+ return isIntN(12, BrOffset);
+ }
+}
+
+void SuperHInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock &NewDestBB,
+ MachineBasicBlock &RestoreBB, const DebugLoc &DL,
+ int64_t BrOffset, RegScavenger *RS) const {
+
+}
+
+
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 78e9d10ae445c..3b309249c8b22 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -35,13 +35,53 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
/// always be able to get register info as well (through this method).
const SuperHRegisterInfo &getRegisterInfo() const { return RI; }
+ /// Gets whether a given opcode can fill a delay slot.
+ ///
+ /// SuperH does not allow branch instructions of any kind to be situated
+ /// in a delay slot, nor does it allow instructions with delay slots
+ /// to be chained together.
+ bool canFillDelaySlot(unsigned Opcode) const;
+ ISD::CondCode getCondFromBranchOp(unsigned Op) const;
+ const MCInstrDesc &getBrCond(ISD::CondCode CC) const;
+
+ // Instruction Info
+
+ /// Return the noop instruction to use for a noop.
+ MCInst getNop() const override;
+ void insertNoop(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI) const override;
+
+
+ // Stack Frames
void copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, const DebugLoc &DL,
Register DestReg, Register SrcReg, bool KillSrc,
bool RenamableDest = false,
bool RenamableSrc = false) const override;
- bool canFillDelaySlot(unsigned Opcode) const;
+ // Branch Analysis
+ bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify = false) const override;
+ unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
+ const DebugLoc &DL,
+ int *BytesAdded = nullptr) const override;
+ unsigned removeBranch(MachineBasicBlock &MBB,
+ int *BytesRemoved = nullptr) const override;
+ bool
+ reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
+
+ MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
+
+ bool isBranchOffsetInRange(unsigned BranchOpc,
+ int64_t BrOffset) const override;
+
+ void insertIndirectBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock &NewDestBB,
+ MachineBasicBlock &RestoreBB, const DebugLoc &DL,
+ int64_t BrOffset, RegScavenger *RS) const override;
};
const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 3d7303b507dbd..deff63e16f00b 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -46,8 +46,14 @@ def ptr_op : RegisterOperand<sh_ptr_rc> {
//===--------------------------------------------------------------------------===//
def SHSDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
-def SHSDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
-def SHSDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
+def SHSDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+def SHSDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
+def SHSDT_PICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
+ SDTCisPtrTy<1>, SDTCisVT<2, i32>]>;
+def SHSDT_Brcond : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisInt<1>]>;
+def SHSDT_Cmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisInt<2>]>;
+def SHSDT_SelectCC : SDTypeProfile<1, 3,
+ [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisInt<3>]>;
//===--------------------------------------------------------------------------===//
// SuperH Specific Nodes
@@ -67,6 +73,15 @@ def SHRetGlue : SDNode<"SHISD::RET_GLUE", SDTNone,
[SDNPHasChain, SDNPOptInGlue,
SDNPVariadic]>;
+def SHWrapper : SDNode<"SHISD::WRAPPER", SDTIntUnaryOp>;
+def SHPICAdd : SDNode<"SHISD::PIC_ADD", SHSDT_PICAdd>;
+
+// Conditional Branching and Comparison
+def SHselectcc : SDNode<"SHISD::SELECT_CC", SHSDT_SelectCC, [SDNPInGlue]>;
+def SHbrcond : SDNode<"SHISD::BRCOND", SHSDT_Brcond, [SDNPHasChain, SDNPInGlue]>;
+def SHcmp : SDNode<"SHISD::CMP", SHSDT_Cmp, [SDNPOutGlue]>;
+
+
//===--------------------------------------------------------------------------===//
// Operand Classes
//===--------------------------------------------------------------------------===//
@@ -126,7 +141,17 @@ def disp4 : SHDispOp<4, i4>;
def disp8 : SHDispOp<8, i8>;
def disp12 : SHDispOp<12, i16>;
+def brtarget : Operand<OtherVT> {
+ let EncoderMethod = "getBranchTargetOpValue";
+ let DecoderMethod = "DecodeBranchTarget";
+ let PrintMethod = "printPCRelImm";
+ let OperandType = "OPERAND_PCREL";
+}
+// An operand for the CONSTPOOL_ENTRY pseudo-instruction.
+def cpinst_operand : Operand<i32> {
+ let PrintMethod = "printCPInstOperand";
+}
// Memory
class SHMemRegOp<RegisterClass regClass>
@@ -136,38 +161,6 @@ class SHMemRegOp<RegisterClass regClass>
}
def GPRMem : SHMemRegOp<GPR>;
-// Memory Indirect (Register + Register)
-def MemRRI : Operand<iPTR> {
- let ParserMatchClass = SHMemClass;
- let OperandType = "OPERAND_MEMORY";
- let MIOperandInfo = (ops GPR, GPR);
-}
-
-// Memory Indirect (Register + Disp)
-def MemRD : Operand<iPTR> {
- let ParserMatchClass = SHMemClass;
- let OperandType = "OPERAND_MEMORY";
- let MIOperandInfo = (ops GPR, disp8);
-}
-
-// Memory Indirect (GBR + disp)
-def MemGBRI : Operand<iPTR> {
- let ParserMatchClass = SHMemClass;
- let OperandType = "OPERAND_MEMORY";
- let MIOperandInfo = (ops R_GBR, disp8);
-}
-
-// Memory Indirect (R0 + disp)
-def MemR0I : Operand<iPTR> {
- let ParserMatchClass = SHMemClass;
- let OperandType = "OPERAND_MEMORY";
- let MIOperandInfo = (ops R_R0, disp8);
-}
-
-// Addressing mode pattern reg+disp
-let WantsRoot = true in
-def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
-
//===--------------------------------------------------------------------------===//
// Predicates
//===--------------------------------------------------------------------------===//
@@ -228,26 +221,26 @@ def MOVI8Rn : InstRnI8<0b1110000000000000,
"mov #$imm,$Rn",
[(set i32:$Rn, imm8:$imm)]>;
-// mov @(disp, PC), R0
+// mova @(disp, PC), R0
let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
def MOVAD8PCR0 : InstD8<0b1100011100000000,
(outs), (ins disp8:$disp),
- "mov @($disp,PC),R0",
- []>;
+ "mova @($disp,PC),R0",
+ [(set R0, (load disp8:$disp))]>;
// mov.w @(disp,PC), Rn
let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
def MOVWD8PCRn : InstRnD8<0b1001000000000000,
(outs GPR:$Rn), (ins disp8:$disp),
"mov.w @($disp,PC),$Rn",
- [(set i32:$Rn, (sextloadi16 addr:$disp))]>;
+ [(set i32:$Rn, (sextloadi16 disp8:$disp))]>;
// mov.l @(disp,PC), Rn
let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
def MOVLD8PCRn : InstRnD8<0b1101000000000000,
(outs GPR:$Rn), (ins disp8:$disp),
"mov.l @($disp,PC),$Rn",
- [(set i32:$Rn, (load addr:$disp))]>;
+ [(set i32:$Rn, (load disp8:$disp))]>;
// movt Rn
def MOVTRn : InstRn<0b0000000000101001,
@@ -490,7 +483,6 @@ let hasSideEffects = 0, mayStore = 1 in {
-
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
// Arithmetic Instructions
@@ -506,17 +498,16 @@ let hasSideEffects = 0, mayStore = 1 in {
let hasSideEffects = 0, Constraints = "$src = $Rn" in {
// add Rm, Rn
- let isCommutable = 1 in
def ADDRmRn : InstRmRn<0b0011000000001100,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"add $Rm,$Rn",
[(set i32:$Rn, (add i32:$Rm, i32:$src))]>;
// add imm:8, Rn
- def ADDI8Rn : InstRnI8<0b0011000000001100,
- (outs GPR:$Rn), (ins imm8:$imm, GPR:$src),
+ def ADDI8Rn : InstRnI8<0b0111000000000000,
+ (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
"add #$imm,$Rn",
- [(set i32:$Rn, (add imm8:$imm, i32:$src))]>;
+ [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
// addc Rm, Rn
let Defs = [SR], Uses = [SR], isCommutable = 1 in
@@ -723,69 +714,64 @@ def CMPSTRRmRn : InstRmRn<0b0010000000001100,
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
+// and Rm,Rn
+let Constraints = "$src = $Rn" in
+def ANDRmRn : InstRmRn<0b0010000000001001,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "and $Rm,$Rn",
+ [(set i32:$Rn, (and i32:$Rm, i32:$src))]>;
+// and #imm,R0
+let Defs = [R0], Uses = [R0] in
+def ANDI8R0 : InstI8<0b1100100100000000,
+ (outs), (ins imm8:$imm),
+ "and #$imm,R0",
+ []>;
-let hasSideEffects = 0 in {
-
- // and Rm,Rn
- let Constraints = "$src = $Rn" in
- def ANDRmRn : InstRmRn<0b0010000000001001,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
- "and $Rm,$Rn",
- []>;
- // and #imm,R0
- let Defs = [R0], Uses = [R0] in
- def ANDI8R0 : InstI8<0b1100100100000000,
- (outs), (ins imm8:$imm),
- "and #$imm,R0",
- []>;
-
- // not Rm,Rn
- let Constraints = "$src = $Rn" in
- def NOTRmRn : InstRmRn<0b0110000000000111,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
- "not $Rm,$Rn",
- []>;
-
- // or Rm,Rn
- let Constraints = "$src = $Rn" in
- def ORRmRn : InstRmRn<0b0010000000001011,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
- "or $Rm,$Rn",
- []>;
- // or #imm,R0
- let Defs = [R0], Uses = [R0] in
- def ORI8R0 : InstI8<0b1100101100000000,
- (outs), (ins imm8:$imm),
- "or #$imm,R0",
- []>;
+// not Rm,Rn
+def NOTRmRn : InstRmRn<0b0110000000000111,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "not $Rm,$Rn",
+ [(set i32:$Rn, (not i32:$Rm))]>;
+
+// or Rm,Rn
+let Constraints = "$src = $Rn" in
+def ORRmRn : InstRmRn<0b0010000000001011,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "or $Rm,$Rn",
+ [(set i32:$Rn, (or i32:$Rm, i32:$src))]>;
+// or #imm,R0
+let Defs = [R0], Uses = [R0] in
+def ORI8R0 : InstI8<0b1100101100000000,
+ (outs), (ins imm8:$imm),
+ "or #$imm,R0",
+ []>;
- // xor Rm,Rn
- let Constraints = "$src = $Rn" in
- def XORRmRn : InstRmRn<0b0010000000001010,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
- "xor $Rm,$Rn",
- []>;
- // xor #imm,R0
- let Defs = [R0], Uses = [R0] in
- def XORI8R0 : InstI8<0b1100101000000000,
- (outs), (ins imm8:$imm),
- "xor #$imm,R0",
- []>;
+// xor Rm,Rn
+let Constraints = "$src = $Rn" in
+def XORRmRn : InstRmRn<0b0010000000001010,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "xor $Rm,$Rn",
+ [(set i32:$Rn, (xor i32:$Rm, i32:$src))]>;
+// xor #imm,R0
+let Defs = [R0], Uses = [R0] in
+def XORI8R0 : InstI8<0b1100101000000000,
+ (outs), (ins imm8:$imm),
+ "xor #$imm,R0",
+ []>;
- // tst Rm,Rn
- let Defs = [SR], Constraints = "$src = $Rn" in
- def TSTRmRn : InstRmRn<0b0010000000001000,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
- "tst $Rm,$Rn",
- []>;
- // tst #imm,R0
- let Defs = [R0, SR], Uses = [R0] in
- def TSTI8R0 : InstI8<0b1100100000000000,
- (outs), (ins imm8:$imm),
- "tst #$imm,R0",
- []>;
+// tst Rm,Rn
+let Defs = [SR] in
+def TSTRmRn : InstRmRn<0b0010000000001000,
+ (outs), (ins GPR:$Rm, GPR:$Rn),
+ "tst $Rm,$Rn",
+ []>;
+// tst #imm,R0
+let Defs = [SR], Uses = [R0] in
+def TSTI8R0 : InstI8<0b1100100000000000,
+ (outs), (ins imm8:$imm),
+ "tst #$imm,R0",
+ []>;
-}
@@ -817,14 +803,14 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
def ROTLRn : InstRn<0b0100000000000100,
(outs GPR:$Rn), (ins GPR:$src),
"rotl $Rn",
- []>;
+ [(set i32:$Rn, (rotl i32:$src, (i8 1)))]>;
// rotr Rn
let Defs = [SR] in
def ROTRRn : InstRn<0b0100000000000101,
(outs GPR:$Rn), (ins GPR:$src),
"rotr $Rn",
- []>;
+ [(set i32:$Rn, (rotr i32:$src, (i8 1)))]>;
// shal Rn
let Defs = [SR] in
@@ -838,58 +824,58 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
def SHARRn : InstRn<0b0100000000100001,
(outs GPR:$Rn), (ins GPR:$src),
"shar $Rn",
- []>;
+ [(set i32:$Rn, (sra i32:$src, (i8 1)))]>;
// shll Rn
let Defs = [SR] in
def SHLLRn : InstRn<0b0100000000000000,
(outs GPR:$Rn), (ins GPR:$src),
"shll $Rn",
- []>;
+ [(set i32:$Rn, (shl i32:$src, (i8 1)))]>;
// shll2 Rn
let Defs = [SR] in
def SHLL2Rn : InstRn<0b0100000000001000,
(outs GPR:$Rn), (ins GPR:$src),
"shll2 $Rn",
- []>;
+ [(set i32:$Rn, (shl i32:$src, (i8 2)))]>;
// shll8 Rn
def SHLL8Rn : InstRn<0b0100000000011000,
(outs GPR:$Rn), (ins GPR:$src),
"shll8 $Rn",
- []>;
+ [(set i32:$Rn, (shl i32:$src, (i8 8)))]>;
// shll16 Rn
def SHLL16Rn : InstRn<0b0100000000101000,
(outs GPR:$Rn), (ins GPR:$src),
"shll16 $Rn",
- []>;
+ [(set i32:$Rn, (shl i32:$src, (i8 16)))]>;
// shlr Rn
let Defs = [SR] in
def SHLRRn : InstRn<0b0100000000000001,
(outs GPR:$Rn), (ins GPR:$src),
"shlr $Rn",
- []>;
+ [(set i32:$Rn, (srl i32:$src, (i8 1)))]>;
// shlr2 Rn
def SHLR2Rn : InstRn<0b0100000000001001,
(outs GPR:$Rn), (ins GPR:$src),
"shlr2 $Rn",
- []>;
+ [(set i32:$Rn, (srl i32:$src, (i8 2)))]>;
// shlr8 Rn
def SHLR8Rn : InstRn<0b0100000000011001,
(outs GPR:$Rn), (ins GPR:$src),
"shlr8 $Rn",
- []>;
+ [(set i32:$Rn, (srl i32:$src, (i8 8)))]>;
// shlr16 Rn
def SHLR16Rn : InstRn<0b0100000000101001,
(outs GPR:$Rn), (ins GPR:$src),
"shlr16 $Rn",
- []>;
+ [(set i32:$Rn, (srl i32:$src, (i8 16)))]>;
}
@@ -900,24 +886,70 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
-// TODO: Port these to the updated way.
-// def BF_Disp : BrOp_Disp8<0b1000101100000000, "bf">;
-// def BFS_Disp : BrOpD_Disp8<0b1000111100000000, "bf/s">;
-// def BT_Disp : BrOp_Disp8<0b1000100100000000, "bt">;
-// def BTS_Disp : BrOpD_Disp8<0b1000110100000000, "bt/s">;
-// def BRA_Disp : BrOp_Disp12<0b1010000000000000, "bra">;
-// def BRAF_Rm : BrOp_Rm<0b0000000000100011, "braf">;
-// def BSR_Disp : BrOp_Disp12<0b1011000000000000, "bsr">;
-// def BSRF_Rm : BrOp_Rm<0b0000000000000011, "bsrf">;
-// def JMP_Rmi : BrOp_Rmi<0b0100000000101011, "jmp">;
+let isTerminator = 1 in {
+ let isBranch = 1, Uses = [SR] in
+ def BF : InstD8<0b1000101100000000,
+ (outs), (ins brtarget:$disp),
+ "bf $disp",
+ []>;
+
+ let isBranch = 1, hasDelaySlot = 1, Uses = [SR] in
+ def BFS : InstD8<0b1000111100000000,
+ (outs), (ins brtarget:$disp),
+ "bf/s $disp",
+ []>;
+
+ let isBranch = 1, Uses = [SR] in
+ def BT : InstD8<0b1000100100000000,
+ (outs), (ins brtarget:$disp),
+ "bt $disp",
+ []>;
+
+ let isBranch = 1, hasDelaySlot = 1, Uses = [SR] in
+ def BTS : InstD8<0b1000110100000000,
+ (outs), (ins brtarget:$disp),
+ "bt/s $disp",
+ []>;
+
+ let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+ def BRA : InstD12<0b1010000000000000,
+ (outs), (ins brtarget:$disp),
+ "bra $disp",
+ [(br bb:$disp)]>;
+
+ let isIndirectBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+ def BRAF : InstRm<0b0000000000100011,
+ (outs), (ins GPR:$Rm),
+ "braf $Rm",
+ []>;
+
+ let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+ def BSR : InstD12<0b1011000000000000,
+ (outs), (ins brtarget:$disp),
+ "bsr $disp",
+ []>;
+
+ let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+ def BSRF : InstRm<0b0000000000000011,
+ (outs), (ins GPR:$Rm),
+ "bsrf $Rm",
+ []>;
+
+ let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+ def JMP : InstRm<0b0100000000101011,
+ (outs), (ins GPR:$Rm),
+ "jmp @$Rm",
+ []>;
+}
+
//===--------------------------------------------------------------------------===//
// Call Instructions
//===--------------------------------------------------------------------------===//
-let isCall = 1, hasDelaySlot = 1 in {
- let Uses = [GBR] in
+let isCall = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in {
+ let Uses = [SR, GBR] in
def JSRRmi : InstRm<0b0100000000001011,
(outs), (ins GPRMem:$Rm),
"jsr @$Rm",
@@ -925,6 +957,9 @@ let isCall = 1, hasDelaySlot = 1 in {
}
+
+
+
//===--------------------------------------------------------------------------===//
// Return Instructions
//===--------------------------------------------------------------------------===//
@@ -1038,7 +1073,7 @@ def LDSLRminciPR : InstRm<0b0100000000100110,
[]>;
// nop
-let hasSideEffects = 1 in
+let hasSideEffects = 1, isTerminator = 1 in
def NOP : Inst<0b0000000000001001, (outs), (ins), "nop", []>;
// rte
@@ -1164,9 +1199,6 @@ include "SuperHInstrDSP.td"
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
-
-
-
//===--------------------------------------------------------------------------===//
// Stack Frame
//===--------------------------------------------------------------------------===//
@@ -1176,6 +1208,15 @@ include "SuperHInstrDSP.td"
let Defs = [SR], hasSideEffects = 0 in
def SHFrmIdx : SHPseudo<(outs GPR:$dst), (ins GPR:$src, disp12:$src2)>;
+/// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in
+/// the function. The first operand is the ID# for this instruction, the second
+/// is the index into the MachineConstantPool that this is, the third is the
+/// size in bytes of this constant pool entry.
+let hasSideEffects = 0, isNotDuplicable = 1, hasNoSchedulingInfo = 1 in
+def CONSTPOOL_ENTRY : SHPseudo<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size),
+ "!CONSTPOOL_ENTRY $instid, $cpidx, $size",
+ []>;
+
let Defs = [R0], Uses = [R0] in {
def ADJCALLSTACKDOWN : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
"!ADJCALLSTACKDOWN $amt1, $amt2",
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index 9e3198be7dddd..d5b7cc883b51f 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "SuperHMCInstLower.h"
+#include "MCTargetDesc/SuperHMCAsmInfo.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
#include "SuperHSubtarget.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCExpr.h"
@@ -18,7 +20,32 @@ namespace llvm {
MCOperand
SuperHMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
const SuperHSubtarget &Subtarget) const {
- const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
+ const MCExpr *Expr = nullptr;
+ switch (MO.getTargetFlags()) {
+ case SHII::MO_NO_FLAG:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_None, Ctx);
+ break;
+
+ case SHII::MO_GOT:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT, Ctx);
+ break;
+
+ case SHII::MO_GOTPC:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_PCREL, Ctx);
+ break;
+
+ case SHII::MO_GOTOFF:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_OFF, Ctx);
+ break;
+
+ case SHII::MO_DIR:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
+ break;
+
+ case SHII::MO_PCREL:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_PCREL, Ctx);
+ break;
+ }
return MCOperand::createExpr(Expr);
}
@@ -52,6 +79,11 @@ void SuperHMCInstLower::lowerInstruction(const MachineInstr &MI,
MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()), Subtarget);
break;
case MachineOperand::MO_MachineBasicBlock:
+
+ // NOTE: Branch instructions will generally jump to labels.
+ // so ensure we emit them if they're referenced in an
+ // operand during lowering.
+ MO.getMBB()->setLabelMustBeEmitted();
MCOp = MCOperand::createExpr(
MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
break;
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
new file mode 100644
index 0000000000000..880835ebafc49
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -0,0 +1,126 @@
+//===-- SuperHMachineFunctionInfo.h - SuperH private data -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file declares the SuperH specific subclass of MachineFunctionInfo.
+///
+//===----------------------------------------------------------------------===//
+
+#include "SuperHMachineFunctionInfo.h"
+#include "SuperHConstantPoolValue.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include <type_traits>
+
+using namespace llvm;
+
+void SuperHMachineFunctionInfo::anchor() {}
+
+MachineFunctionInfo *SuperHMachineFunctionInfo::clone(
+ BumpPtrAllocator &Allocator, MachineFunction &DestMF,
+ const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
+ const {
+ return DestMF.cloneInfo<SuperHMachineFunctionInfo>(*this);
+}
+
+SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
+ GlobalAddressSDNode *N,
+ SelectionDAG &DAG,
+ SHCP::SHCPModifier Modifier) {
+
+ // Early exit for null node.
+ if (!N)
+ return nullptr;
+
+ // Run though the constant pool that is tied to the DAG and search for
+ // the constant there.
+ MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+ for (auto &MC : MCP->getConstants()) {
+ if (MC.isMachineConstantPoolEntry()) {
+ if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+ if (CPV->getGV() == N->getGlobal())
+ return CPV;
+ }
+ }
+ }
+
+ // If not found, create a new one and add it.
+ MachineFunction &MF = DAG.getMachineFunction();
+ SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+ unsigned LabelIndex = SFI->createConstIndex();
+ return SuperHConstantPoolConstant::Create(
+ N->getGlobal(),
+ LabelIndex,
+ SHCP::SHCPKind::CPValue,
+ Modifier
+ );
+}
+
+SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
+ BlockAddressSDNode *N,
+ SelectionDAG &DAG,
+ SHCP::SHCPModifier Modifier) {
+
+ // Early exit for null node.
+ if (!N)
+ return nullptr;
+
+ // Run though the constant pool that is tied to the DAG and search for
+ // the constant there.
+ MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+ for (auto &MC : MCP->getConstants()) {
+ if (MC.isMachineConstantPoolEntry()) {
+ if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+ if (CPV->getBlockAddress() == N->getBlockAddress())
+ return CPV;
+ }
+ }
+ }
+
+ // If not found, create a new one and add it.
+ MachineFunction &MF = DAG.getMachineFunction();
+ SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+ unsigned LabelIndex = SFI->createConstIndex();
+ return SuperHConstantPoolConstant::Create(
+ N->getBlockAddress(),
+ LabelIndex,
+ SHCP::SHCPKind::CPBlockAddress,
+ Modifier
+ );
+}
+
+SuperHConstantPoolSymbol *SuperHMachineFunctionInfo::tryGetConstant(
+ ExternalSymbolSDNode *N,
+ SelectionDAG &DAG,
+ SHCP::SHCPModifier Modifier) {
+
+ // Early exit for null node.
+ if (!N)
+ return nullptr;
+
+ // Run though the constant pool that is tied to the DAG and search for
+ // the constant there.
+ MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+ for (auto &MC : MCP->getConstants()) {
+ if (MC.isMachineConstantPoolEntry()) {
+ if (auto *CPV = (SuperHConstantPoolSymbol*)MC.Val.MachineCPVal) {
+ if (CPV->getSymbol() == N->getSymbol())
+ return CPV;
+ }
+ }
+ }
+
+ // If not found, create a new one and add it.
+ MachineFunction &MF = DAG.getMachineFunction();
+ SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+ unsigned LabelIndex = SFI->createConstIndex();
+ return SuperHConstantPoolSymbol::Create(
+ *DAG.getContext(),
+ N->getSymbol(),
+ LabelIndex
+ );
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
new file mode 100644
index 0000000000000..33264e71670a0
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -0,0 +1,68 @@
+//===-- SuperHMachineFunctionInfo.h - SuperH private data -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file declares the SuperH specific subclass of MachineFunctionInfo.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHMACHINEFUNCTION_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHMACHINEFUNCTION_H
+
+#include "SuperHConstantPoolValue.h"
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/CodeGenTypes/MachineValueType.h"
+
+namespace llvm {
+
+class SuperHMachineFunctionInfo : public MachineFunctionInfo {
+
+ /// CPIndexCount - How many constant pool indices are allocated.
+ unsigned CPIndexCount = 0;
+
+public:
+ explicit SuperHMachineFunctionInfo(const Function &F,
+ const TargetSubtargetInfo *STI) {}
+
+ MachineFunctionInfo *
+ clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
+ const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
+ const override;
+
+ // getConstIndexCount - Gets the amount of PIC Labels that have been
+ // created thus far.
+ unsigned getConstIndexCount() const { return CPIndexCount; }
+
+ // createConstIndex - Creates a new PIC Label UId.
+ unsigned createConstIndex() { return CPIndexCount++; }
+
+ // tryGetConstant - SuperH's compressed instruction set means that
+ // immediates and displacements can not be larger than 8 bits.
+ // As such we need to store said immediates and displacements within
+ // constants that are within range of the program counter.
+ //
+ // As such this function is a helper that:
+ // 1. Allocates a constant pool slot for a given node
+ // 2. Inserts the target into said slot.
+ // 3. Returns the allocated slot, ready to be loaded via
+ // a PC-relative load.
+ SuperHConstantPoolConstant *tryGetConstant(GlobalAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+ SuperHConstantPoolConstant *tryGetConstant(BlockAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+ SuperHConstantPoolSymbol *tryGetConstant(ExternalSymbolSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+
+private:
+ virtual void anchor();
+};
+
+
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index f6053dbb48798..6c40c0f25fdd0 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -69,6 +69,9 @@ BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
// R0 is always reserved as some instructions can only write to it.
Reserved.set(SH::R0);
+ // Reserve GOT pointer
+ Reserved.set(SH::R12);
+
// Also reserve the stack frame and stack pointer.
Reserved.set(SH::R14);
Reserved.set(SH::R15);
@@ -94,11 +97,10 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
if (MI.getOpcode() == SH::SHFrmIdx) {
// TODO: Lower frames that can't be expressed in 4 bits.
-
Register DstReg = MI.getOperand(0).getReg();
MachineInstr *New = BuildMI(MBB, MI, dl, TII.get(SH::MOVLD4RmiRn), DstReg)
.addReg(SH::R14)
- .addImm(Offset / 4);
+ .addImm(Offset);
MI.eraseFromParent();
return false;
@@ -116,4 +118,8 @@ Register SuperHRegisterInfo::getFrameRegister() const {
Register SuperHRegisterInfo::getStackRegister() const {
return SH::R15;
+}
+
+Register SuperHRegisterInfo::getGOTRegister() const {
+ return SH::R12;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index c40cffab52e7a..0a69b4b9a8c2c 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -43,6 +43,7 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
// Helpers
Register getFrameRegister() const;
Register getStackRegister() const;
+ Register getGOTRegister() const;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
index 1cff7f9f647b4..4967df1a71c97 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "SuperHSubtarget.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
#include "MCTargetDesc/SuperHMCTargetDesc.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/TargetRegistry.h"
@@ -24,12 +25,11 @@ using namespace llvm;
#define GET_SUBTARGETINFO_CTOR
#include "SuperHGenSubtargetInfo.inc"
-SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
- const StringRef &FS, const TargetMachine &TM)
- : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, TuneCPU, FS),
+SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
+ const StringRef &FS, const TargetMachine &TM)
+ : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, TuneCPU, FS), TM(TM),
InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
- TLInfo(TM, *this), FrameLowering(*this) {
- // TSInfo = std::make_unique<SuperHSelectionDAGInfo>();
+ TLInfo(TM, *this), TSInfo(), FrameLowering(*this) {
}
SuperHSubtarget::~SuperHSubtarget() = default;
@@ -46,4 +46,110 @@ SuperHSubtarget &SuperHSubtarget::initializeSubtargetDependencies(
// Parse features string.
ParseSubtargetFeatures(CPUName, TuneCPU, FS);
return *this;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Classification Functions
+//===----------------------------------------------------------------------===//
+
+SHRefClass SuperHSubtarget::classifyBlockAddressReference() const {
+ switch (TM.getCodeModel()) {
+ default:
+ llvm_unreachable("Unsupported code model");
+ case CodeModel::Small:
+ case CodeModel::Kernel: {
+ return SHII::MO_PCREL;
+ }
+ case CodeModel::Medium:
+ case CodeModel::Large: {
+ return isPositionIndependent() ?
+ SHII::MO_PCREL :
+ SHII::MO_DIR;
+ }
+ }
+}
+
+SHRefClass SuperHSubtarget::classifyLocalReference(const GlobalValue *GV) const {
+ switch (TM.getCodeModel()) {
+ default:
+ llvm_unreachable("Unsupported code model");
+ case CodeModel::Small:
+ case CodeModel::Kernel: {
+ return isPositionIndependent() ?
+ SHII::MO_PCREL :
+ SHII::MO_DIR;
+ }
+ case CodeModel::Medium: {
+ return isPositionIndependent() ?
+ SHII::MO_GOTOFF :
+ SHII::MO_DIR;
+ }
+ case CodeModel::Large: {
+ return isPositionIndependent() ?
+ SHII::MO_GOTOFF :
+ SHII::MO_DIR;
+ }
+ }
+}
+
+SHRefClass SuperHSubtarget::classifyExternalReference(const Module &M) const {
+ if (TM.shouldAssumeDSOLocal(nullptr))
+ return classifyLocalReference(nullptr);
+
+ return isPositionIndependent() ?
+ SHII::MO_GOTPC :
+ SHII::MO_GOT;
+}
+
+SHRefClass SuperHSubtarget::classifyGlobalReference(const GlobalValue *GV) const {
+ return classifyGlobalReference(GV, *GV->getParent());
+}
+
+SHRefClass SuperHSubtarget::classifyGlobalReference(const GlobalValue *GV,
+ const Module &M) const {
+ if (TM.shouldAssumeDSOLocal(GV))
+ return classifyLocalReference(GV);
+
+ switch (TM.getCodeModel()) {
+ default:
+ llvm_unreachable("Unsupported code model");
+ case CodeModel::Small:
+ case CodeModel::Kernel:
+ case CodeModel::Medium: {
+ return isPositionIndependent() ?
+ SHII::MO_GOTPC :
+ SHII::MO_DIR;
+ }
+ case CodeModel::Large: {
+ return isPositionIndependent() ?
+ SHII::MO_GOTOFF :
+ SHII::MO_DIR;
+ }
+ }
+}
+
+SHRefClass SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
+ const Module &M) const {
+ if (TM.shouldAssumeDSOLocal(GV))
+ return SHII::MO_NO_FLAG;
+
+
+ // If the function is marked as non-lazy, generate an indirect call
+ // which loads from the GOT directly. This avoids run-time overhead
+ // at the cost of eager binding.
+ auto *F = dyn_cast_or_null<Function>(GV);
+ if (F && F->hasFnAttribute(Attribute::NonLazyBind)) {
+ return SHII::MO_GOTPC;
+ }
+
+ return isPositionIndependent() ?
+ SHII::MO_PLT :
+ SHII::MO_DIR;
+}
+
+SHRefClass SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
+ return classifyGlobalFunctionReference(GV, *GV->getParent());
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.h b/llvm/lib/Target/SuperH/SuperHSubtarget.h
index 7a2149e384b51..d3e767935ada7 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.h
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.h
@@ -18,9 +18,11 @@
#include "SuperHISelLowering.h"
#include "SuperHInstrInfo.h"
#include "SuperHSelectionDAGInfo.h"
+#include "SuperHTargetMachine.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/Triple.h"
#define GET_SUBTARGETINFO_HEADER
@@ -29,6 +31,8 @@
namespace llvm {
class StringRef;
+typedef unsigned char SHRefClass;
+
class SuperHSubtarget : public SuperHGenSubtargetInfo {
enum SuperHArchEnum {
SHDefault,
@@ -40,6 +44,7 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
SuperHArchEnum SHArchVersion;
+ const TargetMachine &TM;
SuperHInstrInfo InstrInfo;
SuperHTargetLowering TLInfo;
SuperHSelectionDAGInfo TSInfo;
@@ -50,24 +55,42 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
#include "SuperHGenSubtargetInfo.inc"
public:
- SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
- const StringRef &FS, const TargetMachine &TM);
+ SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
+ const StringRef &FS, const TargetMachine &TM);
~SuperHSubtarget() override;
+ const Triple &getTargetTriple() const { return TM.getTargetTriple(); }
const SuperHInstrInfo *getInstrInfo() const override { return &InstrInfo; }
- const TargetFrameLowering *getFrameLowering() const override {
- return &FrameLowering;
- }
- const SuperHRegisterInfo *getRegisterInfo() const override {
- return &InstrInfo.getRegisterInfo();
- }
- const SuperHSelectionDAGInfo *getSelectionDAGInfo() const override {
- return &TSInfo;
- }
- const SuperHTargetLowering *getTargetLowering() const override {
- return &TLInfo;
- }
+ const TargetFrameLowering *getFrameLowering() const override { return &FrameLowering; }
+ const SuperHRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); }
+ const SuperHSelectionDAGInfo *getSelectionDAGInfo() const override { return &TSInfo; }
+ const SuperHTargetLowering *getTargetLowering() const override { return &TLInfo; }
+
+ bool isTargetELF() const { return getTargetTriple().isOSBinFormatELF(); }
+ bool isPositionIndependent() const { return TM.isPositionIndependent(); }
+
+ // Classification functions
+ SHRefClass classifyLocalReference(const GlobalValue *GV) const;
+
+ /// Classify a global variable reference for the current subtarget according
+ /// to how we should reference it in a non-pcrel context.
+ SHRefClass classifyGlobalReference(const GlobalValue *GV,
+ const Module &M) const;
+ SHRefClass classifyGlobalReference(const GlobalValue *GV) const;
+
+ /// Classify a external variable reference for the current subtarget according
+ /// to how we should reference it in a non-pcrel context.
+ SHRefClass classifyExternalReference(const Module &M) const;
+
+ /// Classify a global function reference for the current subtarget.
+ SHRefClass classifyGlobalFunctionReference(const GlobalValue *GV,
+ const Module &M) const;
+ SHRefClass classifyGlobalFunctionReference(const GlobalValue *GV) const override;
+
+ /// Classify a blockaddress reference for the current subtarget according to
+ /// how we should reference it in a non-pcrel context.
+ SHRefClass classifyBlockAddressReference() const;
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
bool GETTER() const { return ATTRIBUTE; }
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 09befc32c7ead..0d8e004954cac 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -13,11 +13,14 @@
#include "SuperHTargetMachine.h"
#include "SuperH.h"
#include "SuperHSubtarget.h"
+#include "SuperHMachineFunctionInfo.h"
#include "TargetInfo/SuperHTargetInfo.h"
+#include "llvm/CodeGen/BranchFoldingPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/PassRegistry.h"
#include "llvm/Support/Compiler.h"
#include <optional>
@@ -26,6 +29,12 @@ using namespace llvm;
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSuperHTarget() {
RegisterTargetMachine<SuperHTargetMachine> SH(getTheSuperHTarget());
RegisterTargetMachine<SuperHTargetMachine> SHLE(getTheSuperHLETarget());
+
+ PassRegistry &Registry = *PassRegistry::getPassRegistry();
+ initializeSuperHAsmPrinterPass(Registry);
+ initializeSuperHFillDelaySlotsPass(Registry);
+ initializeSuperHConstantIslandsPass(Registry);
+ initializeSuperHDAGToDAGISelLegacyPass(Registry);
}
//
@@ -40,6 +49,8 @@ class SuperHPassConfig : public TargetPassConfig {
bool addInstSelector() override;
void addPreSched2() override;
+ void addPreEmitPass() override;
+ void addPreEmitPass2() override;
SuperHTargetMachine &getSuperHTargetMachine() const {
return getTM<SuperHTargetMachine>();
}
@@ -51,9 +62,22 @@ bool SuperHPassConfig::addInstSelector() {
}
void SuperHPassConfig::addPreSched2() {
+}
+
+void SuperHPassConfig::addPreEmitPass() {
+ addPass(&BranchFolderPassID);
+ addPass(&IfConverterID);
addPass(createSuperHFillDelaySlotsPass());
}
+void SuperHPassConfig::addPreEmitPass2() {
+
+ // Inserts Constant Islands. Block sizes cannot be increased after this point,
+ // as this may push the branch ranges and load offsets of accessing constant
+ // pools out of range.
+ addPass(createSuperHConstantIslandPass());
+}
+
} // namespace
@@ -100,4 +124,11 @@ SuperHTargetMachine::getSubtargetImpl(const Function &F) const {
ST = std::make_unique<SuperHSubtarget>(CPU, TuneCPU, FS, *this);
}
return ST.get();
+}
+
+MachineFunctionInfo *
+SuperHTargetMachine::createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
+ const TargetSubtargetInfo *STI) const {
+ return SuperHMachineFunctionInfo::create<SuperHMachineFunctionInfo>(Allocator, F,
+ STI);
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.h b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
index 3b2872ed50ffd..63b722fff7a57 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.h
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
@@ -33,6 +33,10 @@ class SuperHTargetMachine : public CodeGenTargetMachineImpl {
bool JIT);
~SuperHTargetMachine() override;
+ MachineFunctionInfo *
+ createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
+ const TargetSubtargetInfo *STI) const override;
+
const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override;
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
TargetLoweringObjectFile *getObjFileLowering() const override {
>From e0dc8b97340536328c5f21a551500d18622b693e Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sat, 22 Aug 2026 00:49:48 +0200
Subject: [PATCH 22/39] Handle i1, i8 and i16 sign/zero extend loads and O2+
branches
---
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 3 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 151 ++++++++++++++++--
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 1 +
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 53 ++++++
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 2 -
5 files changed, 191 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 59b297b48f886..252bb5952524d 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -69,8 +69,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
for (MVT VT : MVT::integer_valuetypes()) {
for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
setLoadExtAction(N, VT, MVT::i1, Promote);
- setLoadExtAction(N, VT, MVT::i8, Promote);
- setLoadExtAction(N, VT, MVT::i16, Promote);
+ setLoadExtAction(N, VT, MVT::i64, Expand);
}
}
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 07523d475b3c5..e27b09e12fd4f 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -72,16 +72,25 @@ void SuperHInstrInfo::insertNoop(MachineBasicBlock &MBB,
ISD::CondCode SuperHInstrInfo::getCondFromBranchOp(unsigned Op) const {
switch (Op) {
default:
- return ISD::SETFALSE;
- case SH::BRA:
+ return ISD::SETCC_INVALID;
case SH::NOP:
- return ISD::SETTRUE;
case SH::BT:
case SH::BTS:
- return ISD::SETEQ;
+ return ISD::SETTRUE;
case SH::BF:
case SH::BFS:
- return ISD::SETNE;
+ return ISD::SETFALSE;
+ }
+}
+
+ISD::CondCode SuperHInstrInfo::getOppositeCondCode(ISD::CondCode Op) const {
+ switch (Op) {
+ default:
+ return ISD::SETCC_INVALID;
+ case ISD::SETTRUE:
+ return ISD::SETFALSE;
+ case ISD::SETFALSE:
+ return ISD::SETTRUE;
}
}
@@ -89,13 +98,9 @@ const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
switch (CC) {
default:
llvm_unreachable("Unknown condition code!");
- case ISD::SETEQ:
- case ISD::SETGE:
- case ISD::SETGT:
+ case ISD::SETTRUE:
return get(SH::BT);
- case ISD::SETNE:
- case ISD::SETLE:
- case ISD::SETLT:
+ case ISD::SETFALSE:
return get(SH::BF);
}
}
@@ -151,14 +156,18 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
continue;
}
- LLVM_DEBUG(dbgs() << "analyzeBranch " << getName(I->getOpcode()) << "\n");
-
// Working from the bottom, when we see a non-terminator
// instruction, we're done.
if (!isUnpredicatedTerminator(*I)) {
break;
}
+ // A terminator that isn't a branch can't easily be handled
+ // by this analysis.
+ if (!I->getDesc().isBranch()) {
+ return true;
+ }
+
// Handle unconditional branches.
if (I->getOpcode() == SH::BRA) {
UnCondBrIter = I;
@@ -186,6 +195,56 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
TBB = I->getOperand(0).getMBB();
continue;
}
+
+ // Handle conditional branches.
+ ISD::CondCode BranchCode = getCondFromBranchOp(I->getOpcode());
+ if (BranchCode == ISD::SETFALSE) {
+ return true; // Can't handle indirect branch.
+ }
+
+ // Working from the bottom, handle the first conditional branch.
+ if (Cond.empty()) {
+ MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
+ if (AllowModify && UnCondBrIter != MBB.end() &&
+ MBB.isLayoutSuccessor(TargetBB)) {
+
+ BranchCode = getOppositeCondCode(BranchCode);
+ unsigned JNCC = getBrCond(BranchCode).getOpcode();
+ MachineBasicBlock::iterator OldInst = I;
+
+ BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
+ .addMBB(UnCondBrIter->getOperand(0).getMBB());
+ BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SH::BRA))
+ .addMBB(TargetBB);
+
+ OldInst->eraseFromParent();
+ UnCondBrIter->eraseFromParent();
+
+ // Restart the analysis.
+ UnCondBrIter = MBB.end();
+ I = MBB.end();
+ continue;
+ }
+
+ // Handle subsequent conditional branches. Only handle the case where all
+ // conditional branches branch to the same destination.
+ assert(Cond.size() == 1);
+ assert(TBB);
+
+ // Only handle the case where all conditional branches branch to
+ // the same destination.
+ if (TBB != I->getOperand(0).getMBB()) {
+ return true;
+ }
+
+ ISD::CondCode OldBranchCode = (ISD::CondCode)Cond[0].getImm();
+ // If the conditions are the same, we can leave them alone.
+ if (OldBranchCode == BranchCode) {
+ continue;
+ }
+
+ return true;
+ }
}
return false;
@@ -195,17 +254,79 @@ unsigned SuperHInstrInfo::insertBranch(MachineBasicBlock &MBB, MachineBasicBlock
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
const DebugLoc &DL,
int *BytesAdded) const {
- return 0;
+ if (BytesAdded)
+ *BytesAdded = 0;
+
+ // Shouldn't be a fall through.
+ assert(TBB && "insertBranch must not be told to insert a fallthrough");
+ assert((Cond.size() == 1 || Cond.size() == 0) &&
+ "SH branch conditions have one component!");
+
+ if (Cond.empty()) {
+ assert(!FBB && "Unconditional branch with multiple successors!");
+ auto &MI = *BuildMI(&MBB, DL, get(SH::BRA)).addMBB(TBB);
+ if (BytesAdded)
+ *BytesAdded += getInstSizeInBytes(MI);
+ return 1;
+ }
+
+ // Conditional branch.
+ unsigned Count = 0;
+ ISD::CondCode CC = (ISD::CondCode)Cond[0].getImm();
+ auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
+
+ if (BytesAdded)
+ *BytesAdded += getInstSizeInBytes(CondMI);
+ ++Count;
+
+ if (FBB) {
+ // Two-way Conditional branch. Insert the second branch.
+ auto &MI = *BuildMI(&MBB, DL, get(SH::BRA)).addMBB(FBB);
+ if (BytesAdded)
+ *BytesAdded += getInstSizeInBytes(MI);
+ ++Count;
+ }
+
+ return Count;
}
unsigned SuperHInstrInfo::removeBranch(MachineBasicBlock &MBB,
int *BytesRemoved) const {
- return 0;
+ if (BytesRemoved)
+ *BytesRemoved = 0;
+
+ MachineBasicBlock::iterator I = MBB.end();
+ unsigned Count = 0;
+
+ while (I != MBB.begin()) {
+ --I;
+ if (I->isDebugInstr()) {
+ continue;
+ }
+
+ if (I->getOpcode() != SH::BRA &&
+ getCondFromBranchOp(I->getOpcode()) == ISD::SETCC_INVALID) {
+ break;
+ }
+
+ // Remove the branch.
+ if (BytesRemoved)
+ *BytesRemoved += getInstSizeInBytes(*I);
+ I->eraseFromParent();
+ I = MBB.end();
+ ++Count;
+ }
+
+ return Count;
}
bool
SuperHInstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+ assert(Cond.size() == 1 && "Invalid SH branch condition!");
+ ISD::CondCode CC = static_cast<ISD::CondCode>(Cond[0].getImm());
+ Cond[0].setImm(getOppositeCondCode(CC));
+ return false;
}
MachineBasicBlock *SuperHInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 3b309249c8b22..da25ff9390727 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -42,6 +42,7 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
/// to be chained together.
bool canFillDelaySlot(unsigned Opcode) const;
ISD::CondCode getCondFromBranchOp(unsigned Op) const;
+ ISD::CondCode getOppositeCondCode(ISD::CondCode CC) const;
const MCInstrDesc &getBrCond(ISD::CondCode CC) const;
// Instruction Info
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index deff63e16f00b..6826583a17c80 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -636,6 +636,38 @@ let hasSideEffects = 0, isCommutable = 1 in {
+//===--------------------------------------------------------------------------===//
+// Sign/Zero Extend
+//===--------------------------------------------------------------------------===//
+
+// exts.b Rm, Rn
+def EXTSBRmRn : InstRmRn<0b0110000000001110,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "exts.b $Rm,$Rn",
+ [(set i32:$Rn, (sext i8:$Rm))]>;
+
+// exts.w Rm, Rn
+def EXTSWRmRn : InstRmRn<0b0110000000001111,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "exts.w $Rm,$Rn",
+ [(set i32:$Rn, (sext i16:$Rm))]>;
+
+// extu.b Rm, Rn
+def EXTUBRmRn : InstRmRn<0b0110000000001100,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "extu.b $Rm,$Rn",
+ [(set i32:$Rn, (zext i8:$Rm))]>;
+
+// extu.w Rm, Rn
+def EXTUWRmRn : InstRmRn<0b0110000000001101,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "extu.w $Rm,$Rn",
+ [(set i32:$Rn, (zext i16:$Rm))]>;
+
+
+
+
+
//===--------------------------------------------------------------------------===//
// Comparison
//===--------------------------------------------------------------------------===//
@@ -1193,6 +1225,27 @@ include "SuperHInstrDSP.td"
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Non-Instruction Patterns
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+//===--------------------------------------------------------------------------===//
+// Zero-Extend Load
+//===--------------------------------------------------------------------------===//
+
+def : Pat<(i32 (zextloadi1 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
+def : Pat<(i32 (zextloadi8 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
+def : Pat<(i32 (zextloadi16 i32:$src)), (EXTUWRmRn (MOVWRmiRn i32:$src))>;
+def : Pat<(i32 (extloadi1 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+def : Pat<(i32 (extloadi8 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+def : Pat<(i32 (extloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
+
+
+
+
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
// Pseudo instructions
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 0d8e004954cac..86a4a4c41bd85 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -65,8 +65,6 @@ void SuperHPassConfig::addPreSched2() {
}
void SuperHPassConfig::addPreEmitPass() {
- addPass(&BranchFolderPassID);
- addPass(&IfConverterID);
addPass(createSuperHFillDelaySlotsPass());
}
>From ee5999754de95d6cd3a642351439f0ac98066662 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 31 Aug 2026 05:01:43 +0200
Subject: [PATCH 23/39] Fix little endian target name to match GCC
---
clang/lib/Basic/Targets.cpp | 2 +-
llvm/include/llvm/TargetParser/Triple.h | 4 ++--
.../SuperH/TargetInfo/SuperHTargetInfo.cpp | 4 ++--
llvm/lib/TargetParser/TargetDataLayout.cpp | 4 ++--
llvm/lib/TargetParser/Triple.cpp | 22 +++++++++----------
5 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index d6e73b6678f3f..bdff3e1605b18 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -554,7 +554,7 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
}
case llvm::Triple::sh:
- case llvm::Triple::sh_le:
+ case llvm::Triple::shl:
switch (os) {
default:
return std::make_unique<SuperHTargetInfo>(Triple, Opts);
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 709137eacb9e0..9c7fde7f3d059 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -80,7 +80,7 @@ class Triple {
riscv32be, // RISC-V (32-bit, big endian): riscv32be
riscv64be, // RISC-V (64-bit, big endian): riscv64be
sh, // SuperH (big endian): sh
- sh_le, // SuperH (little endian): sh_le
+ shl, // SuperH (little endian): shl
sparc, // Sparc: sparc
sparcv9, // Sparcv9: Sparcv9
sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
@@ -1108,7 +1108,7 @@ class Triple {
/// Tests whether the target is SuperH.
bool isSuperH() const {
- return getArch() == Triple::sh || getArch() == Triple::sh_le;
+ return getArch() == Triple::sh || getArch() == Triple::shl;
}
/// Tests whether the target is SystemZ.
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
index 83c5970fc6783..f206de2dabc90 100644
--- a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
@@ -26,6 +26,6 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeSuperHTargetInfo() {
RegisterTarget<Triple::sh, /*HasJIT=*/false> X(getTheSuperHTarget(),
"sh", "SuperH (big endian)", "SuperH");
- RegisterTarget<Triple::sh_le, /*HasJIT=*/false> Y(getTheSuperHLETarget(),
- "sh_le", "SuperH (little endian)", "SuperH");
+ RegisterTarget<Triple::shl, /*HasJIT=*/false> Y(getTheSuperHLETarget(),
+ "shl", "SuperH (little endian)", "SuperH");
}
diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp
index 1c87d82305e7b..2dc69abf12064 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -555,7 +555,7 @@ static std::string computeVEDataLayout(const Triple &T) {
static std::string computeSuperHDataLayout(const Triple &T) {
// Mixed-endian
- std::string Ret = T.getArch() == Triple::sh_le ? "e" : "E";
+ std::string Ret = T.getArch() == Triple::shl ? "e" : "E";
// ELF name manging
Ret += "-m:e";
@@ -644,7 +644,7 @@ std::string Triple::computeDataLayout(StringRef ABIName) const {
case Triple::systemz:
return computeSystemZDataLayout(*this);
case Triple::sh:
- case Triple::sh_le:
+ case Triple::shl:
return computeSuperHDataLayout(*this);
case Triple::tce:
return "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:32-"
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 3e62300a726de..4172c998949aa 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -108,8 +108,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
return "riscv64be";
case sh:
return "sh";
- case sh_le:
- return "sh_le";
+ case shl:
+ return "shl";
case shave:
return "shave";
case sparc:
@@ -693,7 +693,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("riscv64be", riscv64be)
.Case("hexagon", hexagon)
.Case("sh", sh)
- .Case("sh_le", sh_le)
+ .Case("shl", shl)
.Case("sparc", sparc)
.Case("sparcel", sparcel)
.Case("sparcv9", sparcv9)
@@ -848,7 +848,7 @@ Triple::ArchType Triple::parseArch(StringRef ArchName) {
.Case("hexagon", Triple::hexagon)
.Cases({"s390x", "systemz"}, Triple::systemz)
.Case("sh", Triple::sh)
- .Case("sh_le", Triple::sh_le)
+ .Case("shl", Triple::shl)
.Case("sparc", Triple::sparc)
.Case("sparcel", Triple::sparcel)
.Cases({"sparcv9", "sparc64"}, Triple::sparcv9)
@@ -1238,7 +1238,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::riscv32be:
case Triple::riscv64be:
case Triple::sh:
- case Triple::sh_le:
+ case Triple::shl:
case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
@@ -2003,7 +2003,7 @@ unsigned Triple::getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::riscv32:
case llvm::Triple::riscv32be:
case llvm::Triple::sh:
- case llvm::Triple::sh_le:
+ case llvm::Triple::shl:
case llvm::Triple::shave:
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
@@ -2116,7 +2116,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::riscv32:
case Triple::riscv32be:
case Triple::sh:
- case Triple::sh_le:
+ case Triple::shl:
case Triple::shave:
case Triple::sparc:
case Triple::sparcel:
@@ -2210,7 +2210,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::msp430:
case Triple::r600:
case Triple::sh:
- case Triple::sh_le:
+ case Triple::shl:
case Triple::shave:
case Triple::sparcel:
case Triple::tce:
@@ -2391,7 +2391,7 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::sparcel:
T.setArch(Triple::sparc);
break;
- case Triple::sh_le:
+ case Triple::shl:
T.setArch(Triple::sh);
break;
case Triple::tcele:
@@ -2450,7 +2450,7 @@ Triple Triple::getLittleEndianArchVariant() const {
T.setArch(Triple::sparcel);
break;
case Triple::sh:
- T.setArch(Triple::sh_le);
+ T.setArch(Triple::shl);
break;
case Triple::tce:
T.setArch(Triple::tcele);
@@ -2492,7 +2492,7 @@ bool Triple::isLittleEndian() const {
case Triple::riscv32:
case Triple::riscv64:
case Triple::shave:
- case Triple::sh_le:
+ case Triple::shl:
case Triple::sparcel:
case Triple::spir64:
case Triple::spir:
>From 2803a9e7dcc0ad7aa2c3b31d41072e40ff8d82db Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 1 Sep 2026 09:11:00 +0200
Subject: [PATCH 24/39] Refactor ASM parser
---
.../SuperH/AsmParser/SuperHAsmParser.cpp | 566 +++++++++++++-----
.../SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp | 3 +-
llvm/lib/Target/SuperH/SuperH.td | 5 +-
3 files changed, 409 insertions(+), 165 deletions(-)
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 5fa685f814828..6e45a5388068e 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -36,6 +36,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/LogicalResult.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DebugLog.h"
@@ -44,6 +45,8 @@
#include <sstream>
#include <system_error>
+#define DEBUG_TYPE "sh-asmparser"
+
using namespace llvm;
// The generated AsmMatcher SparcGenAsmMatcher uses "SuperH" as the target
@@ -72,9 +75,6 @@ class SuperHAsmParser : public MCTargetAsmParser {
#define GET_ASSEMBLER_HEADER
#include "SuperHGenAsmMatcher.inc"
- bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
- ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
- MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override;
ParseStatus parseDirective(AsmToken DirectiveID) override;
bool parseGNUAttribute(SMLoc L);
@@ -83,9 +83,26 @@ class SuperHAsmParser : public MCTargetAsmParser {
uint64_t &ErrorInfo,
bool MatchingInlineAsm) override;
+ // Register Parsing
+ ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
+ bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
+
+ // Parser helpers.
+ MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
+ ParseStatus tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc);
+ ParseStatus tryParseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc);
+ ParseStatus tryParseRegRelative(MCRegister &BaseReg, MCRegister &OffReg, const MCExpr *&Offset, SMLoc &StartLoc, SMLoc &EndLoc);
+ ParseStatus tryParseRegIndirect(MCRegister &Reg, bool &IsInc, bool &IsDec, SMLoc &StartLoc, SMLoc &EndLoc);
+
+ // Parser entry points
ParseStatus parseOperand(OperandVector &Operands);
- ParseStatus parseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc);
- ParseStatus parseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc);
+ ParseStatus parseRegister(OperandVector &Operands);
+ ParseStatus parseRegisterIndirect(OperandVector &Operands);
+ ParseStatus parseRegisterIndirectInc(OperandVector &Operands);
+ ParseStatus parseRegisterIndirectDec(OperandVector &Operands);
+ ParseStatus parsePCRel(OperandVector &Operands);
+ ParseStatus parseImm(OperandVector &Operands);
+ ParseStatus parseDisp(OperandVector &Operands);
public:
SuperHAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII)
@@ -108,7 +125,9 @@ class SuperHOperand : public MCParsedAsmOperand {
rk_FR32,
rk_FR64,
rk_VEC128,
- rk_XMTRX
+ rk_XMTRX,
+ rk_SYS,
+ rk_CTRL,
};
private:
@@ -144,10 +163,6 @@ class SuperHOperand : public MCParsedAsmOperand {
const MCExpr *Val;
};
- struct DispOp {
- const MCExpr *Val;
- };
-
struct ExprOp {
const MCExpr *Val;
};
@@ -162,7 +177,6 @@ class SuperHOperand : public MCParsedAsmOperand {
struct Token Tok;
struct RegOp Reg;
struct ImmOp Imm;
- struct DispOp Disp;
struct MemOp Mem;
struct ExprOp Expr;
unsigned ASI;
@@ -180,6 +194,7 @@ class SuperHOperand : public MCParsedAsmOperand {
bool isMem() const override { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec | k_IndirectIndex)) != 0; }
bool isIndirectReg() const { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec)) != 0; }
bool isAnyReg() const { return isReg() || isIndirectReg(); }
+ bool isPCRel() const { return Kind == k_Displacement && Mem.Base == SH::PC; }
SMLoc getStartLoc() const override { return StartLoc; }
SMLoc getEndLoc() const override { return EndLoc; }
@@ -206,6 +221,17 @@ class SuperHOperand : public MCParsedAsmOperand {
this->addExpr(Inst, Expr);
}
+ void addPCRelOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCExpr *Expr = getDisp();
+ this->addExpr(Inst, Expr);
+ }
+
+ void addIRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getReg()));
+ }
+
void addExpr(MCInst &Inst, const MCExpr *Expr) const{
// Add as immediate when possible. Null MCExpr = 0.
if (!Expr)
@@ -233,7 +259,7 @@ class SuperHOperand : public MCParsedAsmOperand {
const MCExpr *getDisp() const {
assert((Kind & k_Displacement) && "Invalid access!");
- return Disp.Val;
+ return Mem.Offset;
}
const MCExpr *getOffset() const {
@@ -268,17 +294,19 @@ class SuperHOperand : public MCParsedAsmOperand {
return Op;
}
- static std::unique_ptr<SuperHOperand> CreateDisp(const MCExpr *Val, SMLoc S, SMLoc E) {
+ static std::unique_ptr<SuperHOperand> CreateDisp(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {
auto Op = std::make_unique<SuperHOperand>(k_Displacement);
- Op->Imm.Val = Val;
+ Op->Mem.Base = Reg;
+ Op->Mem.Offset = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static std::unique_ptr<SuperHOperand> CreateSymRef(const MCExpr *Val, SMLoc S, SMLoc E) {
- auto Op = std::make_unique<SuperHOperand>(k_Immediate | k_Displacement);
- Op->Imm.Val = Val;
+ auto Op = std::make_unique<SuperHOperand>(k_Displacement);
+ Op->Mem.Base = SH::PC;
+ Op->Mem.Offset = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
@@ -332,10 +360,10 @@ class SuperHOperand : public MCParsedAsmOperand {
static std::unique_ptr<SuperHOperand> CreateFromExpr(const MCExpr *Expr,
SMLoc S, SMLoc E) {
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
- return CreateDisp(CE, S, E);
+ return CreateDisp(SH::PC, CE, S, E);
if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
- return CreateDisp(SRE, S, E);
+ return CreateSymRef(SRE, S, E);
}
return CreateExpr(Expr, S, E);
@@ -376,44 +404,42 @@ class SuperHOperand : public MCParsedAsmOperand {
MCRegister SuperHAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegKind) {
RegKind = SuperHOperand::rk_None;
- if(!Tok.is(AsmToken::Identifier))
+ if(Tok.isNot(AsmToken::Identifier))
return SH::NoRegister;
- StringRef Name = Tok.getString();
- MCRegister Reg = MatchRegisterName(Name.lower());
- if (Reg) {
-
- // XMTRX register.
- if (Reg == SH::XMTRX) {
- RegKind = SuperHOperand::rk_XMTRX;
- return Reg;
- }
-
+ std::string Name = Tok.getString().lower();
+ MCRegister Reg = MatchRegisterName(Name);
+ if (MRI.getRegClass(SH::GPRRegClassID).contains(Reg)) {
+
// General purpose register class.
- if (MRI.getRegClass(SH::GPRRegClassID).contains(Reg)) {
- RegKind = SuperHOperand::rk_GPR;
- return Reg;
- }
-
+ RegKind = SuperHOperand::rk_GPR;
+ } else if (Reg == SH::XMTRX) {
+
+ // XMTRX register.
+ RegKind = SuperHOperand::rk_XMTRX;
+ } else if (MRI.getRegClass(SH::SYSRegClassID).contains(Reg)) {
+
+ // System register class.
+ RegKind = SuperHOperand::rk_SYS;
+ } else if (MRI.getRegClass(SH::CTRLRegClassID).contains(Reg)) {
+
+ // Control register class.
+ RegKind = SuperHOperand::rk_CTRL;
+ } else if (MRI.getRegClass(SH::FR32RegClassID).contains(Reg)) {
+
// 32-bit float registers.
- if (MRI.getRegClass(SH::FR32RegClassID).contains(Reg)) {
- RegKind = SuperHOperand::rk_FR32;
- return Reg;
- }
-
+ RegKind = SuperHOperand::rk_FR32;
+ } else if (MRI.getRegClass(SH::FR64RegClassID).contains(Reg)) {
+
// 64-bit float registers.
- if (MRI.getRegClass(SH::FR64RegClassID).contains(Reg)) {
- RegKind = SuperHOperand::rk_FR64;
- return Reg;
- }
-
+ RegKind = SuperHOperand::rk_FR64;
+ } else if (MRI.getRegClass(SH::VEC128RegClassID).contains(Reg)) {
+
// 128-bit vector registers.
- if (MRI.getRegClass(SH::VEC128RegClassID).contains(Reg)) {
- RegKind = SuperHOperand::rk_VEC128;
- return Reg;
- }
+ RegKind = SuperHOperand::rk_VEC128;
}
- return SH::NoRegister;
+
+ return Reg;
}
bool SuperHAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) {
@@ -430,7 +456,7 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
// SuperH Registers are in the form of an identifier.
Reg = SH::NoRegister;
- if (getLexer().getKind() != AsmToken::Identifier)
+ if (getLexer().isNot(AsmToken::Identifier))
return ParseStatus::NoMatch;
// Match.
@@ -443,165 +469,392 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
return ParseStatus::Success;
}
-ParseStatus SuperHAsmParser::parseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
- const AsmToken &Tok = Parser.getTok();
- const MCExpr *Expr;
+
+
+
+//===----------------------------------------------------------------------===//
+// Parser Helpers
+//===----------------------------------------------------------------------===//
+
+// Try parsing a register by its name.
+ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc) {
+ const AsmToken Tok = Parser.getTok();
StartLoc = Tok.getLoc();
EndLoc = Tok.getEndLoc();
+ // SuperH Registers are in the form of an identifier.
+ Reg = SH::NoRegister;
+ if (getLexer().isNot(AsmToken::Identifier))
+ return ParseStatus::NoMatch;
+
+ // Match.
+ Reg = matchRegisterName(Tok, RegKind);
+ if (RegKind == SuperHOperand::rk_None)
+ return ParseStatus::NoMatch;
+
+ // Consume the register.
+ Parser.Lex();
+ return ParseStatus::Success;
+}
+
+// Parses register relative addressing modes.
+ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister &OffReg,
+ const MCExpr *&Offset, SMLoc &StartLoc,
+ SMLoc &EndLoc) {
+ const AsmToken Tok = getTok();
+ unsigned RegKind;
+
+ // NOTE: SuperH Assemblers support subtituting the normal PC-relative form
+ // with a symbol reference.
+ //
+ // The following instruction sequences are equivalent:
+ // mova .ABC, r0
+ // mova @(.ABC,pc), r0
+ // mova @(8,pc), r0 (Where 8 is an offset from PC that refers
+ // to the same address as the identifier would)
+ if (getTok().is(AsmToken::Identifier)) {
+
+ // Registers are *not* identifiers.
+ if (matchRegisterName(getTok(), RegKind) != SH::NoRegister) {
+ return ParseStatus::NoMatch;
+ }
+
+ auto *Sym = getContext().getOrCreateSymbol(getTok().getIdentifier());
+ Offset = MCSymbolRefExpr::create(Sym, getContext());
+ BaseReg = SH::PC;
+ Parser.Lex();
+ return ParseStatus::Success;
+ }
+
+ // Parse "@(" sequence
+ if (getTok().isNot(AsmToken::At))
+ return ParseStatus::NoMatch;
+ Parser.Lex();
+
+ if (getTok().isNot(AsmToken::LParen)) {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
+ Parser.Lex();
+
+ // Parse identifier
+ if (getTok().is(AsmToken::Identifier)) {
+
+ // Try parsing base-register as well as identifiers.
+ if (tryParseRegister(OffReg, RegKind, StartLoc, EndLoc).isNoMatch()) {
+
+ auto *Sym = getContext().getOrCreateSymbol(getTok().getIdentifier());
+ Offset = MCSymbolRefExpr::create(Sym, getContext());
+ Parser.Lex();
+ }
+ } else if (getTok().is(AsmToken::Integer)) {
+
+ // Try parsing numeric displacements.
+ if (Parser.parseExpression(Offset, EndLoc)) {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
+ } else {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
+
+ // Parse seperator
+ if (getTok().isNot(AsmToken::Comma)) {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
+ Parser.Lex();
+
+ // Parse base register
+ if (tryParseRegister(BaseReg, RegKind, StartLoc, EndLoc).isNoMatch()) {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
+
+ // Whoops! missing ending parenthesis.
+ if (getTok().isNot(AsmToken::RParen)) {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
+
+ Parser.Lex();
+ return ParseStatus::Success;
+}
+
+// Parses register-indirect addressing in the following forms:
+//
+// @Rn - Register Indirect
+// @-Rn - Register Indirect with Pre-decrement
+// @Rn+ - Register Indirect with Post-increment
+ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, bool &IsDec,
+ SMLoc &StartLoc, SMLoc &EndLoc) {
+ const AsmToken Tok = Parser.getTok();
+ SMLoc S = StartLoc;
+ SMLoc E = EndLoc;
+ unsigned RegKind;
+
+ if (getTok().isNot(AsmToken::At))
+ return ParseStatus::NoMatch;
+ Parser.Lex();
+
+ // Parse possible pre-decement
+ if (getTok().is(AsmToken::Minus)) {
+ IsDec = true;
+ Parser.Lex();
+ }
+
+ // Parse Register
+ if (tryParseRegister(Reg, RegKind, S, E).isNoMatch()) {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
+
+ // Parse possible post-increment
+ if (Tok.is(AsmToken::Plus)) {
+ IsInc = true;
+ Parser.Lex();
+ }
+
+ // You can't do both increment and decrement.
+ // this is just a straight up syntax error.
+ if (IsInc && IsDec) {
+ getLexer().UnLex(Tok);
+ return Error(getTok().getLoc(), "either pre-decrement or post-increment expected");
+ }
+
+ EndLoc = Parser.getTok().getLoc();
+ return ParseStatus::Success;
+}
+
+ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
+ const AsmToken Tok = Parser.getTok();
+ const MCExpr *Expr;
+
// Eat % and $ which are used in SuperH asm.
if (Tok.is(AsmToken::Percent) || Tok.is(AsmToken::Dollar))
Parser.Lex();
if (Parser.parseExpression(Expr, EndLoc))
- return ParseStatus::Failure;
+ return ParseStatus::NoMatch;
if (Expr->evaluateAsAbsolute(Imm))
return ParseStatus::Success;
- return ParseStatus::Failure;
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
}
-ParseStatus SuperHAsmParser::parseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc) {
- const AsmToken &Tok = Parser.getTok();
- StartLoc = Tok.getLoc();
- EndLoc = Tok.getEndLoc();
- Reg = matchRegisterName(Tok, RegKind);
- if (Reg) {
- Parser.Lex();
+
+//===----------------------------------------------------------------------===//
+// Parser Entrypoints
+//===----------------------------------------------------------------------===//
+
+ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
+ SMLoc StartLoc = getLexer().getLoc();
+ SMLoc EndLoc = getLexer().getLoc();
+
+ // Immediates are prefixed with a #
+ if (getTok().isNot(AsmToken::Hash)) {
+ return ParseStatus::NoMatch;
+ }
+
+ int64_t Imm;
+ if (tryParseImm(Imm, StartLoc, EndLoc).isSuccess()) {
+ EndLoc = getLexer().getLoc();
+ Operands.push_back(SuperHOperand::CreateImm(
+ MCConstantExpr::create(Imm, getContext()),
+ StartLoc,
+ EndLoc
+ ));
return ParseStatus::Success;
}
- return ParseStatus::Failure;
+
+ return ParseStatus::NoMatch;
}
-ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
- const AsmToken &Tok = Parser.getTok();
+ParseStatus SuperHAsmParser::parseDisp(OperandVector &Operands) {
+ return ParseStatus::NoMatch;
+}
+
+ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
+ const AsmToken Tok = Parser.getTok();
SMLoc StartLoc = getLexer().getLoc();
SMLoc EndLoc = getLexer().getLoc();
+
+ // Parse register relative.
+ MCRegister BaseReg;
+ MCRegister OffReg;
+ const MCExpr *Offset;
+ if (tryParseRegRelative(BaseReg, OffReg, Offset, StartLoc, EndLoc).isNoMatch()) {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
+ // Base register must be PC for this type.
+ if (BaseReg != SH::PC) {
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+ }
- switch(Tok.getKind()) {
- default: {
-
- // Try parsing as register first.
- unsigned RegKind;
- MCRegister Reg;
- if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
- Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
- return ParseStatus::Success;
- }
+ EndLoc = getLexer().getLoc();
+ Operands.push_back(SuperHOperand::CreateSymRef(Offset, StartLoc, EndLoc));
+ return ParseStatus::Success;
+}
- // That failed, try parsing as expression.
- const MCExpr *EVal;
- if (Parser.parseExpression(EVal, EndLoc))
- return ParseStatus::Failure;
+ParseStatus SuperHAsmParser::parseRegister(OperandVector &Operands) {
+ SMLoc StartLoc = getLexer().getLoc();
+ SMLoc EndLoc = getLexer().getLoc();
- Operands.push_back(SuperHOperand::CreateFromExpr(EVal, StartLoc, EndLoc));
+ MCRegister Reg;
+ unsigned RegKind;
+ if (tryParseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+ Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
return ParseStatus::Success;
}
- // Immediates.
- case llvm::AsmToken::Hash: {
- Parser.Lex();
- int64_t Imm;
- if (parseImm(Imm, StartLoc, EndLoc).isSuccess()) {
- const MCExpr *Val = MCConstantExpr::create(Imm, getContext());
- Operands.push_back(SuperHOperand::CreateImm(Val, StartLoc, EndLoc));
- return ParseStatus::Success;
- }
+ return ParseStatus::NoMatch;
+}
- // Un-lex on error
- getLexer().UnLex(Tok);
- return ParseStatus::Failure;
+ParseStatus SuperHAsmParser::parseRegisterIndirect(OperandVector &Operands) {
+ const AsmToken Tok = Parser.getTok();
+ SMLoc StartLoc = getLexer().getLoc();
+ SMLoc EndLoc = getLexer().getLoc();
+
+ bool IsInc, IsDec;
+ MCRegister Reg;
+
+ ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
+ if (!Result.isSuccess())
+ return Result;
+
+ // We're only looking for base register indirect here.
+ if (!IsInc && !IsDec) {
+ EndLoc = getLexer().getLoc();
+ Operands.push_back(SuperHOperand::CreateIReg(Reg, StartLoc, EndLoc));
+ return ParseStatus::Success;
}
- // Indirect Memory Access.
- case AsmToken::At: {
- Parser.Lex();
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+}
- // Handle the different kinds of indirect memory access.
- switch(Parser.getTok().getKind()) {
- default: {
- getLexer().UnLex(Tok);
- return ParseStatus::Failure;
- }
-
- // Handle Register Indirect with Pre-Decrement.
- case AsmToken::Minus: {
- Parser.Lex();
+ParseStatus SuperHAsmParser::parseRegisterIndirectInc(OperandVector &Operands) {
+ const AsmToken Tok = Parser.getTok();
+ SMLoc StartLoc = getLexer().getLoc();
+ SMLoc EndLoc = getLexer().getLoc();
- unsigned RegKind;
- MCRegister Reg;
- if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
- Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
- return ParseStatus::Success;
- }
+ bool IsInc, IsDec;
+ MCRegister Reg;
- getLexer().UnLex(Tok);
- return ParseStatus::Failure;
- }
+ ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
+ if (!Result.isSuccess())
+ return Result;
+
+ // We're only looking for register indirect inc here.
+ if (IsInc && !IsDec) {
+ EndLoc = getLexer().getLoc();
+ Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
+ return ParseStatus::Success;
+ }
+
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+}
- // Register Indirect
- case AsmToken::Identifier: {
+ParseStatus SuperHAsmParser::parseRegisterIndirectDec(OperandVector &Operands) {
+ const AsmToken Tok = Parser.getTok();
+ SMLoc StartLoc = getLexer().getLoc();
+ SMLoc EndLoc = getLexer().getLoc();
- unsigned RegKind;
- MCRegister Reg;
- if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+ bool IsInc, IsDec;
+ MCRegister Reg;
- // Handle Register Indirect with Increment.
- if (Parser.getTok().is(AsmToken::Plus)) {
- Parser.Lex();
+ ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
+ if (!Result.isSuccess())
+ return Result;
- Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
- return ParseStatus::Success;
- }
+ // We're only looking for register indirect dec here.
+ if (!IsInc && IsDec) {
+ EndLoc = getLexer().getLoc();
+ Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
+ return ParseStatus::Success;
+ }
- Operands.push_back(SuperHOperand::CreateIReg(Reg, StartLoc, EndLoc));
- return ParseStatus::Success;
- }
+ getLexer().UnLex(Tok);
+ return ParseStatus::NoMatch;
+}
- getLexer().UnLex(Tok);
- return ParseStatus::Failure;
- }
- }
+ParseStatus SuperHAsmParser::parseDirective(AsmToken DirectiveID) {
+ StringRef IDVal = DirectiveID.getIdentifier();
- // Un-lex on error
- getLexer().UnLex(Tok);
- return ParseStatus::Failure;
+ if (IDVal.starts_with(".gnu_attribute")) {
+ if (parseGNUAttribute(DirectiveID.getLoc()))
+ return ParseStatus::Success;
+ }
+ if (IDVal.equals_insensitive(".little")) {
+ return ParseStatus::Success;
}
+ if (IDVal.equals_insensitive(".big")) {
+ return ParseStatus::Success;
}
+ return ParseStatus::NoMatch;
}
-bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) {
+ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
+ switch (getLexer().getKind()) {
+ default:
+ return ParseStatus::NoMatch;
+
+ case AsmToken::Identifier:
+ // Try to parse a register, fall through to the next case if it fails.
+ if (parseRegister(Operands).isSuccess()) {
+ Parser.Lex();
+ return ParseStatus::Success;
+ }
+ return ParseStatus::NoMatch;
+ }
+}
+
+bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Mnemonic,
+ SMLoc NameLoc, OperandVector &Operands) {
// Match mnemonic.
- bool MS = SuperHCheckMnemonic(Name, this->getAvailableFeatures(), 0);
+ bool MS = SuperHCheckMnemonic(Mnemonic, this->getAvailableFeatures(), 0);
if (!MS) {
return Error(NameLoc, "invalid instruction mnemonic" +
- SuperHMnemonicSpellCheck(Name, getAvailableFeatures(), 0));
+ SuperHMnemonicSpellCheck(Mnemonic, getAvailableFeatures(), 0));
}
// Chomp name and add it to the operands.
- Operands.push_back(SuperHOperand::CreateToken(Name, NameLoc));
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ Operands.push_back(SuperHOperand::CreateToken(Mnemonic, NameLoc));
+ int OperandNum = -1;
+ while (getLexer().isNot(AsmToken::EndOfStatement)) {
+ OperandNum++;
+ if (OperandNum > 0) {
+ if (getLexer().is(AsmToken::Comma)) {
+ Parser.Lex();
+ }
+ }
+
+ ParseStatus Result = MatchOperandParserImpl(Operands, Mnemonic);
+ if (Result.isSuccess()) {
+ continue;
+ }
+
+ if (Result.isFailure()) {
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, "unexpected token");
+ }
// Initial operand
if (!parseOperand(Operands).isSuccess()) {
SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token");
}
-
- // Followup operands.
- while (getLexer().is(AsmToken::Comma)) {
- Parser.Lex();
-
- // Parse and remember operand.
- if (!parseOperand(Operands).isSuccess()) {
- SMLoc Loc = getLexer().getLoc();
- return Error(Loc, "unexpected token");
- }
- }
}
// Consume EndOfStatement
@@ -609,15 +862,6 @@ bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Nam
return false;
}
-ParseStatus SuperHAsmParser::parseDirective(AsmToken DirectiveID) {
- StringRef IDVal = DirectiveID.getIdentifier();
- if (IDVal.starts_with(".gnu_attribute"))
- parseGNUAttribute(DirectiveID.getLoc());
- else
- return ParseStatus::NoMatch;
- return ParseStatus::Success;
-}
-
bool SuperHAsmParser::parseGNUAttribute(SMLoc L) {
int64_t Tag;
int64_t IntegerValue;
@@ -633,6 +877,8 @@ bool SuperHAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
uint64_t &ErrorInfo,
bool MatchingInlineAsm) {
+
+ LLVM_DEBUG(dbgs() << "matchAndEmitInstruction\n");
MCInst Inst;
unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
switch(MatchResult) {
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
index 7596ece4b12ec..d5d415def0389 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -22,8 +22,7 @@ SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
const MCTargetOptions &Options)
: MCAsmInfoELF(Options) {
this->IsLittleEndian = TheTriple.isLittleEndian();
- this->CommentString = ";";
- this->SeparatorString = "\n";
+ this->CommentString = "!";
this->InternalSymbolPrefix = ".L";
this->PrivateLabelPrefix = ".L";
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index 03809c4d7a31d..c68ba20059187 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -133,9 +133,8 @@ def SuperHAsmParser : AsmParser {
def SuperHAsmParserVariant : AsmParserVariant {
let Variant = 0;
let Name = "GCC";
- let SeparatorCharacters = " \t,()@-+";
- let TokenizingCharacters = "[]*!#";
- let CommentDelimiter = ";";
+ let TokenizingCharacters = "()+-@";
+ let CommentDelimiter = "!";
}
//===----------------------------------------------------------------------===//
>From b4facd6c367cc815a7c19c24dad9a66b951f91e2 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 1 Sep 2026 09:20:37 +0200
Subject: [PATCH 25/39] Fix parseImm
---
.../SuperH/AsmParser/SuperHAsmParser.cpp | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 6e45a5388068e..80f8f7dd17c97 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -629,20 +629,16 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
const AsmToken Tok = Parser.getTok();
- const MCExpr *Expr;
// Eat % and $ which are used in SuperH asm.
- if (Tok.is(AsmToken::Percent) || Tok.is(AsmToken::Dollar))
+ if (getTok().is(AsmToken::Percent) || getTok().is(AsmToken::Dollar))
Parser.Lex();
- if (Parser.parseExpression(Expr, EndLoc))
+ if (Parser.parseAbsoluteExpression(Imm)) {
+ getLexer().UnLex(Tok);
return ParseStatus::NoMatch;
-
- if (Expr->evaluateAsAbsolute(Imm))
- return ParseStatus::Success;
-
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
+ }
+ return ParseStatus::Success;
}
@@ -652,6 +648,7 @@ ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &E
//===----------------------------------------------------------------------===//
ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
+ const AsmToken Tok = Parser.getTok();
SMLoc StartLoc = getLexer().getLoc();
SMLoc EndLoc = getLexer().getLoc();
@@ -659,10 +656,10 @@ ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
if (getTok().isNot(AsmToken::Hash)) {
return ParseStatus::NoMatch;
}
+ Parser.Lex();
int64_t Imm;
if (tryParseImm(Imm, StartLoc, EndLoc).isSuccess()) {
- EndLoc = getLexer().getLoc();
Operands.push_back(SuperHOperand::CreateImm(
MCConstantExpr::create(Imm, getContext()),
StartLoc,
@@ -671,6 +668,7 @@ ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
return ParseStatus::Success;
}
+ getLexer().UnLex(Tok);
return ParseStatus::NoMatch;
}
>From c0442a7b91dcb598e4ae0b05733c9991278ca732 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 1 Sep 2026 12:17:17 +0200
Subject: [PATCH 26/39] Refactor InstPrinter
---
.../SuperH/AsmParser/SuperHAsmParser.cpp | 179 +++++++-----------
.../SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 45 ++++-
.../SuperH/MCTargetDesc/SuperHInstPrinter.h | 6 +
llvm/lib/Target/SuperH/SuperH.td | 2 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 65 +++++--
5 files changed, 166 insertions(+), 131 deletions(-)
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 80f8f7dd17c97..69500eceaaaa6 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -98,8 +98,6 @@ class SuperHAsmParser : public MCTargetAsmParser {
ParseStatus parseOperand(OperandVector &Operands);
ParseStatus parseRegister(OperandVector &Operands);
ParseStatus parseRegisterIndirect(OperandVector &Operands);
- ParseStatus parseRegisterIndirectInc(OperandVector &Operands);
- ParseStatus parseRegisterIndirectDec(OperandVector &Operands);
ParseStatus parsePCRel(OperandVector &Operands);
ParseStatus parseImm(OperandVector &Operands);
ParseStatus parseDisp(OperandVector &Operands);
@@ -192,8 +190,10 @@ class SuperHOperand : public MCParsedAsmOperand {
bool isReg() const override { return Kind == k_Register; }
bool isDisp() const { return Kind == k_Displacement; }
bool isMem() const override { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec | k_IndirectIndex)) != 0; }
- bool isIndirectReg() const { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec)) != 0; }
- bool isAnyReg() const { return isReg() || isIndirectReg(); }
+ bool isIReg() const { return Kind == k_IndirectReg; }
+ bool isIRegInc() const { return Kind == k_IndirectRegInc; }
+ bool isIRegDec() const { return Kind == k_IndirectRegDec; }
+ bool isAnyReg() const { return isReg() || isIReg() || isIRegInc() || isIRegDec(); }
bool isPCRel() const { return Kind == k_Displacement && Mem.Base == SH::PC; }
SMLoc getStartLoc() const override { return StartLoc; }
@@ -378,18 +378,18 @@ class SuperHOperand : public MCParsedAsmOperand {
}
// Indirect register has @ prefix.
- if (isIndirectReg())
+ if (isIReg())
OS << "@";
// Pre-decrement.
- if (Kind == k_IndirectRegDec)
+ if (isIRegDec())
OS << "-";
// Register or other symbol.
OS << StrFromLoc(this->getStartLoc(), this->getEndLoc());
// Indirect Post-Increment.
- if (Kind == k_IndirectRegInc)
+ if (isIRegInc())
OS << "+";
}
};
@@ -450,18 +450,13 @@ bool SuperHAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &End
ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) {
unsigned RegKind;
- const AsmToken &Tok = Parser.getTok();
+ const AsmToken Tok = Parser.getTok();
StartLoc = Tok.getLoc();
EndLoc = Tok.getEndLoc();
- // SuperH Registers are in the form of an identifier.
- Reg = SH::NoRegister;
- if (getLexer().isNot(AsmToken::Identifier))
- return ParseStatus::NoMatch;
-
// Match.
Reg = matchRegisterName(Tok, RegKind);
- if (RegKind == SuperHOperand::rk_None)
+ if (Reg == SH::NoRegister)
return ParseStatus::NoMatch;
// Consume the register.
@@ -482,14 +477,9 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, unsigned &RegKind
StartLoc = Tok.getLoc();
EndLoc = Tok.getEndLoc();
- // SuperH Registers are in the form of an identifier.
- Reg = SH::NoRegister;
- if (getLexer().isNot(AsmToken::Identifier))
- return ParseStatus::NoMatch;
-
// Match.
Reg = matchRegisterName(Tok, RegKind);
- if (RegKind == SuperHOperand::rk_None)
+ if (Reg == SH::NoRegister)
return ParseStatus::NoMatch;
// Consume the register.
@@ -526,16 +516,15 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
return ParseStatus::Success;
}
- // Parse "@(" sequence
- if (getTok().isNot(AsmToken::At))
- return ParseStatus::NoMatch;
- Parser.Lex();
+ AsmToken Buf[2];
+ getLexer().peekTokens(Buf);
- if (getTok().isNot(AsmToken::LParen)) {
- getLexer().UnLex(Tok);
+ // Parse "@(" sequence
+ if (Buf[0].isNot(AsmToken::At) && Buf[1].isNot(AsmToken::LParen)) {
return ParseStatus::NoMatch;
}
Parser.Lex();
+ Parser.Lex();
// Parse identifier
if (getTok().is(AsmToken::Identifier)) {
@@ -550,35 +539,30 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
} else if (getTok().is(AsmToken::Integer)) {
// Try parsing numeric displacements.
- if (Parser.parseExpression(Offset, EndLoc)) {
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
- }
+ int64_t Disp;
+ ParseStatus Result = tryParseImm(Disp, StartLoc, EndLoc);
+ if (!Result.isSuccess())
+ return Result;
+
+ Offset = MCConstantExpr::create(Disp, getContext());
} else {
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
+
+ return Error(getTok().getLoc(), "expected identifier, register or displacement");
}
// Parse seperator
- if (getTok().isNot(AsmToken::Comma)) {
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
- }
- Parser.Lex();
+ if (parseToken(AsmToken::Comma, "expected ','"))
+ return ParseStatus::Failure;
// Parse base register
- if (tryParseRegister(BaseReg, RegKind, StartLoc, EndLoc).isNoMatch()) {
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
- }
+ ParseStatus Result = tryParseRegister(BaseReg, RegKind, StartLoc, EndLoc);
+ if (!Result.isSuccess())
+ return ParseStatus::Failure;
// Whoops! missing ending parenthesis.
- if (getTok().isNot(AsmToken::RParen)) {
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
- }
+ if (parseToken(AsmToken::RParen, "expected ')'"))
+ return ParseStatus::Failure;
- Parser.Lex();
return ParseStatus::Success;
}
@@ -594,27 +578,21 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
SMLoc E = EndLoc;
unsigned RegKind;
- if (getTok().isNot(AsmToken::At))
+ if (!Parser.parseOptionalToken(AsmToken::At))
return ParseStatus::NoMatch;
- Parser.Lex();
// Parse possible pre-decement
- if (getTok().is(AsmToken::Minus)) {
+ if (Parser.parseOptionalToken(AsmToken::Minus))
IsDec = true;
- Parser.Lex();
- }
// Parse Register
- if (tryParseRegister(Reg, RegKind, S, E).isNoMatch()) {
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
+ if (!tryParseRegister(Reg, RegKind, S, E).isSuccess()) {
+ return ParseStatus::Failure;
}
// Parse possible post-increment
- if (Tok.is(AsmToken::Plus)) {
+ if (Parser.parseOptionalToken(AsmToken::Plus))
IsInc = true;
- Parser.Lex();
- }
// You can't do both increment and decrement.
// this is just a straight up syntax error.
@@ -638,6 +616,8 @@ ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &E
getLexer().UnLex(Tok);
return ParseStatus::NoMatch;
}
+
+ EndLoc = Parser.getTok().getLoc();
return ParseStatus::Success;
}
@@ -648,15 +628,14 @@ ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &E
//===----------------------------------------------------------------------===//
ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
+ LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
const AsmToken Tok = Parser.getTok();
SMLoc StartLoc = getLexer().getLoc();
SMLoc EndLoc = getLexer().getLoc();
- // Immediates are prefixed with a #
- if (getTok().isNot(AsmToken::Hash)) {
+ // Immediates start with a '#'
+ if (!Parser.parseOptionalToken(AsmToken::Hash))
return ParseStatus::NoMatch;
- }
- Parser.Lex();
int64_t Imm;
if (tryParseImm(Imm, StartLoc, EndLoc).isSuccess()) {
@@ -673,10 +652,12 @@ ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
}
ParseStatus SuperHAsmParser::parseDisp(OperandVector &Operands) {
+ LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
return ParseStatus::NoMatch;
}
ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
+ LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
const AsmToken Tok = Parser.getTok();
SMLoc StartLoc = getLexer().getLoc();
SMLoc EndLoc = getLexer().getLoc();
@@ -685,15 +666,13 @@ ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
MCRegister BaseReg;
MCRegister OffReg;
const MCExpr *Offset;
- if (tryParseRegRelative(BaseReg, OffReg, Offset, StartLoc, EndLoc).isNoMatch()) {
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
- }
+ ParseStatus Result = tryParseRegRelative(BaseReg, OffReg, Offset, StartLoc, EndLoc);
+ if (!Result.isSuccess())
+ return Result;
// Base register must be PC for this type.
if (BaseReg != SH::PC) {
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
+ return Error(getTok().getLoc(), "expected PC-relative displacement");
}
EndLoc = getLexer().getLoc();
@@ -702,20 +681,27 @@ ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
}
ParseStatus SuperHAsmParser::parseRegister(OperandVector &Operands) {
- SMLoc StartLoc = getLexer().getLoc();
- SMLoc EndLoc = getLexer().getLoc();
+ LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
+ const AsmToken Tok = Parser.getTok();
+ SMLoc StartLoc = Tok.getLoc();
+ SMLoc EndLoc = Tok.getEndLoc();
MCRegister Reg;
unsigned RegKind;
if (tryParseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+ LLVM_DEBUG({
+ dbgs() << __FUNCTION__ << " (next): ";
+ getTok().dump(dbgs());
+ dbgs() << "\n";
+ });
Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
return ParseStatus::Success;
}
-
return ParseStatus::NoMatch;
}
ParseStatus SuperHAsmParser::parseRegisterIndirect(OperandVector &Operands) {
+ LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
const AsmToken Tok = Parser.getTok();
SMLoc StartLoc = getLexer().getLoc();
SMLoc EndLoc = getLexer().getLoc();
@@ -727,60 +713,30 @@ ParseStatus SuperHAsmParser::parseRegisterIndirect(OperandVector &Operands) {
if (!Result.isSuccess())
return Result;
- // We're only looking for base register indirect here.
+ // Indirect
if (!IsInc && !IsDec) {
+
EndLoc = getLexer().getLoc();
Operands.push_back(SuperHOperand::CreateIReg(Reg, StartLoc, EndLoc));
return ParseStatus::Success;
}
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
-}
-
-ParseStatus SuperHAsmParser::parseRegisterIndirectInc(OperandVector &Operands) {
- const AsmToken Tok = Parser.getTok();
- SMLoc StartLoc = getLexer().getLoc();
- SMLoc EndLoc = getLexer().getLoc();
-
- bool IsInc, IsDec;
- MCRegister Reg;
-
- ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
- if (!Result.isSuccess())
- return Result;
+ // Indirect Pre-Decrement
+ if (!IsInc && IsDec) {
- // We're only looking for register indirect inc here.
- if (IsInc && !IsDec) {
EndLoc = getLexer().getLoc();
- Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
+ Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
return ParseStatus::Success;
}
- getLexer().UnLex(Tok);
- return ParseStatus::NoMatch;
-}
-
-ParseStatus SuperHAsmParser::parseRegisterIndirectDec(OperandVector &Operands) {
- const AsmToken Tok = Parser.getTok();
- SMLoc StartLoc = getLexer().getLoc();
- SMLoc EndLoc = getLexer().getLoc();
-
- bool IsInc, IsDec;
- MCRegister Reg;
-
- ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
- if (!Result.isSuccess())
- return Result;
+ // Indirect Post-Increment
+ if (IsInc && !IsDec) {
- // We're only looking for register indirect dec here.
- if (!IsInc && IsDec) {
EndLoc = getLexer().getLoc();
- Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
+ Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
return ParseStatus::Success;
}
- getLexer().UnLex(Tok);
return ParseStatus::NoMatch;
}
@@ -806,12 +762,7 @@ ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
return ParseStatus::NoMatch;
case AsmToken::Identifier:
- // Try to parse a register, fall through to the next case if it fails.
- if (parseRegister(Operands).isSuccess()) {
- Parser.Lex();
- return ParseStatus::Success;
- }
- return ParseStatus::NoMatch;
+ return parseRegister(Operands);
}
}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index fadac2158f630..b9190f15263f3 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -41,9 +41,47 @@ void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
OS << StringRef(getRegisterName(Reg)).lower();
}
+void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ OS << Op.getImm();
+}
+
+void SuperHInstPrinter::printImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ OS << "#" << Op.getImm();
+}
+
+void SuperHInstPrinter::printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ OS << "@" << StringRef(getRegisterName(Op.getReg())).lower();
+}
+
+void SuperHInstPrinter::printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ OS << "@" << StringRef(getRegisterName(Op.getReg())).lower() << "+";
+}
+
+void SuperHInstPrinter::printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ OS << "@-" << StringRef(getRegisterName(Op.getReg())).lower();
+}
+
void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address,
- unsigned OpNo, raw_ostream &O) {
- printOperand(MI, OpNo, O);
+ unsigned OpNo, raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+
+ // Print standalone symbol.
+ if (Op.isExpr()) {
+ if (const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op.getExpr())) {
+ O << SymOp->getSymbol().getName();
+ return;
+ }
+ }
+
+ // Print immediate value.
+ if (Op.isImm()) {
+ O << "@(" << Op.getImm() << ",pc)";
+ }
}
void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
@@ -52,7 +90,6 @@ void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_
void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
-
// Print Register
if (Op.isReg()) {
@@ -62,7 +99,7 @@ void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostrea
// Print immediates
if (Op.isImm()) {
- O << Op.getImm();
+ O << "#" << Op.getImm();
return;
}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index f22b48ac733b8..ea462c6087c49 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -48,7 +48,13 @@ class SuperHInstPrinter : public MCInstPrinter {
private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
+ void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostream &O);
};
} // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index c68ba20059187..eb404c67e61b5 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -133,7 +133,7 @@ def SuperHAsmParser : AsmParser {
def SuperHAsmParserVariant : AsmParserVariant {
let Variant = 0;
let Name = "GCC";
- let TokenizingCharacters = "()+-@";
+ let TokenizingCharacters = "()+-@#";
let CommentDelimiter = "!";
}
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 6826583a17c80..98b3fd921a5a4 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -96,20 +96,30 @@ class SHOpClass<string name,
// Immediates
class SHImmClass<int width> : SHOpClass<"Imm" # width> {
- let PredicateMethod = "isImm";
- let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isImm";
+ let ParserMethod = "parseImm";
+ let RenderMethod = "addImmOperands";
}
// Displacements
class SHDispClass<int width> : SHOpClass<"Disp" # width> {
- let PredicateMethod = "isDisp";
- let RenderMethod = "addDispOperands";
+ let PredicateMethod = "isDisp";
+ let ParserMethod = "parseDisp";
+ let RenderMethod = "addDispOperands";
}
-// Memory Ops
-def SHMemClass : SHOpClass<"Mem"> {
- let PredicateMethod = "isMem";
- let RenderMethod = "addMemOperands";
+// PC-Relative Addressing
+class SHPCRelClass : SHOpClass<"PCRel"> {
+ let PredicateMethod = "isPCRel";
+ let ParserMethod = "parsePCRel";
+ let RenderMethod = "addPCRelOperands";
+}
+
+// Register Indirect Ops
+class SHRegIndirectClass<string op> : SHOpClass<"IReg" # op> {
+ let PredicateMethod = "isIReg" # op;
+ let ParserMethod = "parseRegisterIndirect";
+ let RenderMethod = "addIRegOperands";
}
//===--------------------------------------------------------------------------===//
@@ -121,6 +131,7 @@ class SHImmOp<int width, ValueType vt>
: Operand<vt> {
let ParserMatchClass = SHImmClass<width>;
let OperandType = "OPERAND_IMMEDIATE";
+ let PrintMethod = "printImm";
let MCOperandPredicate = [{int64_t Imm; return MCOp.evaluateAsConstantImm(Imm) ? isInt<}] # width # [{>(Imm) : false;}];
}
def imm8 : SHImmOp<8, i32>, ImmLeaf<i32, [{ return isInt<8>(Imm); }]>;
@@ -130,6 +141,7 @@ class SHDispOp<int width, ValueType vt>
: Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
let ParserMatchClass = SHDispClass<width>;
let OperandType = "OPERAND_IMMEDIATE";
+ let PrintMethod = "printDisp";
let MCOperandPredicate = [{
int64_t Imm;
if (MCOp.evaluateAsConstantImm(Imm))
@@ -141,7 +153,28 @@ def disp4 : SHDispOp<4, i4>;
def disp8 : SHDispOp<8, i8>;
def disp12 : SHDispOp<12, i16>;
+// PC-Relative Adressing
+class SHPCRelOp<int width, ValueType vt>
+ : Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
+ let ParserMatchClass = SHPCRelClass<>;
+ let OperandType = "OPERAND_PCREL";
+ let EncoderMethod = "getPCRelOpValue";
+ let DecoderMethod = "DecodePCRelDisp";
+ let PrintMethod = "printPCRelImm";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isUInt<#width>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
+}
+
+def pcrel8 : SHPCRelOp<8, i8>;
+def pcrel12 : SHPCRelOp<12, i16>;
+
+// Branch Targets
def brtarget : Operand<OtherVT> {
+ let ParserMatchClass = SHPCRelClass<>;
let EncoderMethod = "getBranchTargetOpValue";
let DecoderMethod = "DecodeBranchTarget";
let PrintMethod = "printPCRelImm";
@@ -153,13 +186,21 @@ def cpinst_operand : Operand<i32> {
let PrintMethod = "printCPInstOperand";
}
-// Memory
-class SHMemRegOp<RegisterClass regClass>
+// Register Indirect
+class SHIndirectRegOp<RegisterClass regClass, string op>
: RegisterOperand<regClass> {
- let ParserMatchClass = SHMemClass;
+ let ParserMatchClass = SHRegIndirectClass<op>;
let OperandType = "OPERAND_MEMORY";
+ let PrintMethod = "printIReg" # op;
}
-def GPRMem : SHMemRegOp<GPR>;
+def IGPR : SHIndirectRegOp<GPR, "">;
+def IGPRInc : SHIndirectRegOp<GPR, "Inc">;
+def IGPRDec : SHIndirectRegOp<GPR, "Dec">;
+
+// Addressing mode pattern reg+imm6
+let WantsRoot = true in
+def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
+
//===--------------------------------------------------------------------------===//
// Predicates
>From 33b9b84e44e5d1901676ef538b03c8a71ab8500e Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 2 Sep 2026 04:24:04 +0200
Subject: [PATCH 27/39] Refactor register name getter
---
.../Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 12 ++++++++----
.../Target/SuperH/MCTargetDesc/SuperHInstPrinter.h | 4 +++-
llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp | 8 +++++---
3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index b9190f15263f3..22fc26b77b3e7 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -37,8 +37,12 @@ namespace llvm {
SuperHInstPrinter::SuperHInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
const MCRegisterInfo &MRI) : MCInstPrinter(MAI, MII, MRI) {}
+const std::string SuperHInstPrinter::getRegName(MCRegister Reg) {
+ return StringRef(getRegisterName(Reg)).lower();
+}
+
void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
- OS << StringRef(getRegisterName(Reg)).lower();
+ OS << getRegName(Reg);
}
void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
@@ -53,17 +57,17 @@ void SuperHInstPrinter::printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O
void SuperHInstPrinter::printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
- OS << "@" << StringRef(getRegisterName(Op.getReg())).lower();
+ OS << "@" << getRegName(Op.getReg());
}
void SuperHInstPrinter::printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
- OS << "@" << StringRef(getRegisterName(Op.getReg())).lower() << "+";
+ OS << "@" << getRegName(Op.getReg()) << "+";
}
void SuperHInstPrinter::printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
- OS << "@-" << StringRef(getRegisterName(Op.getReg())).lower();
+ OS << "@-" << getRegName(Op.getReg());
}
void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address,
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index ea462c6087c49..17af288324675 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -39,13 +39,15 @@ class SuperHInstPrinter : public MCInstPrinter {
void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
unsigned OpIdx, unsigned PrintMethodIdx,
const MCSubtargetInfo &STI, raw_ostream &O);
- static const char *getRegisterName(MCRegister Reg);
void printRegName(raw_ostream &OS, MCRegister Reg) override;
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &OS) override;
+ static const std::string getRegName(MCRegister Reg);
+
private:
+ static const char *getRegisterName(MCRegister Reg);
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index 884266d52eff9..d3dc1cad8ba3f 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -70,8 +70,8 @@ class SuperHAsmPrinter : public AsmPrinter {
void emitConstantPool() override { }
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
- static const char *getRegisterName(MCRegister Reg) {
- return SuperHInstPrinter::getRegisterName(Reg);
+ static std::string getRegisterName(MCRegister Reg) {
+ return SuperHInstPrinter::getRegName(Reg);
}
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -118,7 +118,7 @@ void SuperHAsmPrinter::printOperand(const MachineInstr *MI, int OpNo, raw_ostrea
switch (MO.getType()) {
case MachineOperand::MO_Register:
- O << StringRef(getRegisterName(MO.getReg())).lower();
+ O << getRegisterName(MO.getReg());
break;
case MachineOperand::MO_Immediate:
O << MO.getImm();
@@ -177,6 +177,8 @@ bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned Op
void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
const DataLayout &DL = getDataLayout();
int Size = DL.getTypeAllocSize(MCPV->getType());
+ if (Size < 4)
+ Size = 4;
MCSymbol *MCSym;
SuperHConstantPoolValue *SCPV = static_cast<SuperHConstantPoolValue*>(MCPV);
>From 6057522440500e96881922a6249d5ea7712175c8 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 2 Sep 2026 04:24:36 +0200
Subject: [PATCH 28/39] Remove duplicate error messages from
MatchOperandParserImpl
---
.../lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 69500eceaaaa6..210d023b71dee 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -597,8 +597,7 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
// You can't do both increment and decrement.
// this is just a straight up syntax error.
if (IsInc && IsDec) {
- getLexer().UnLex(Tok);
- return Error(getTok().getLoc(), "either pre-decrement or post-increment expected");
+ return Error(E, "either pre-decrement or post-increment expected");
}
EndLoc = Parser.getTok().getLoc();
@@ -689,11 +688,6 @@ ParseStatus SuperHAsmParser::parseRegister(OperandVector &Operands) {
MCRegister Reg;
unsigned RegKind;
if (tryParseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
- LLVM_DEBUG({
- dbgs() << __FUNCTION__ << " (next): ";
- getTok().dump(dbgs());
- dbgs() << "\n";
- });
Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
return ParseStatus::Success;
}
@@ -792,10 +786,11 @@ bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Mne
continue;
}
+ // NOTE: All the Failure states are Errors in of themselves,
+ // as such we don't return an error in this branch.
if (Result.isFailure()) {
- SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
- return Error(Loc, "unexpected token");
+ return true;
}
// Initial operand
>From 9e5b1fb00e5966355075129c110e72f9f3dcca97 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 2 Sep 2026 04:30:37 +0200
Subject: [PATCH 29/39] Add error message for missing register operand
---
llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 210d023b71dee..47a01005d4e46 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -557,7 +557,7 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
// Parse base register
ParseStatus Result = tryParseRegister(BaseReg, RegKind, StartLoc, EndLoc);
if (!Result.isSuccess())
- return ParseStatus::Failure;
+ return Error(StartLoc, "expected register");
// Whoops! missing ending parenthesis.
if (parseToken(AsmToken::RParen, "expected ')'"))
@@ -587,7 +587,7 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
// Parse Register
if (!tryParseRegister(Reg, RegKind, S, E).isSuccess()) {
- return ParseStatus::Failure;
+ return Error(E, "expected register");
}
// Parse possible post-increment
>From 56c75cb4596f5d03350e48254a1c1704ca72fab2 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 04:51:29 +0200
Subject: [PATCH 30/39] Switch .align to match GAS
---
llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp | 6 ++++++
llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
index d5d415def0389..6ea386dbc1825 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -25,4 +25,10 @@ SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
this->CommentString = "!";
this->InternalSymbolPrefix = ".L";
this->PrivateLabelPrefix = ".L";
+ this->MinInstAlignment = 1;
+
+ // NOTE: GAS SH Assembly uses Log2(N) alignment specifiers,
+ // we replicate those here.
+ this->AlignmentIsInBytes = false;
+ this->HasFunctionAlignment = true;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
index 0dfc47b66f766..232d952eb05f8 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
@@ -32,7 +32,7 @@ class SuperHMCAsmInfo : public MCAsmInfoELF {
public:
explicit SuperHMCAsmInfo(const Triple &TheTriple,
- const MCTargetOptions &Options);
+ const MCTargetOptions &Options);
};
namespace SH {
>From 5692ca7eddbba2a7cd95c1369a09b0b8291e0c52 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 04:52:09 +0200
Subject: [PATCH 31/39] Fix tryParseRegRelative token check
---
llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 47a01005d4e46..e4921dbac6cb5 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -516,11 +516,8 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
return ParseStatus::Success;
}
- AsmToken Buf[2];
- getLexer().peekTokens(Buf);
-
// Parse "@(" sequence
- if (Buf[0].isNot(AsmToken::At) && Buf[1].isNot(AsmToken::LParen)) {
+ if (getTok().isNot(AsmToken::At) || getLexer().peekTok().isNot(AsmToken::LParen)) {
return ParseStatus::NoMatch;
}
Parser.Lex();
>From 1ac495acd96ee0c5ae36c7755cf1f505ee6d5901 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 04:52:37 +0200
Subject: [PATCH 32/39] Align constpool entries to 32-bits
---
llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
index 226136c6fd73f..8703f20fd2c1d 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
+++ b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
@@ -730,6 +730,7 @@ bool SuperHConstantIslands::handleConstantPoolUser(unsigned CPUserIndex,
// We are adding new water. Update NewWaterList.
NewWaterList.insert(NewIsland);
}
+
// Always align the new block because CP entries can be smaller than 4
// bytes. Be careful not to decrease the existing alignment, e.g. NewMBB may
// be an already aligned constant pool block.
@@ -1101,7 +1102,7 @@ SuperHConstantIslands::doInitialConstPlacement(std::vector<MachineInstr *> &CPEM
// move functions around based on their alignment.
// Special case: halfword literals still need word alignment on the function.
Align FuncAlign = MaxAlign;
- if (MaxAlign == 2)
+ if (FuncAlign < 4)
FuncAlign = Align(4);
MF->ensureAlignment(FuncAlign);
>From 0357dbffc5028a8668620694ab9f5338652673e4 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 04:53:16 +0200
Subject: [PATCH 33/39] Refactor loads and stores to use pseudo-op
---
.../SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 113 +++++--
.../SuperH/MCTargetDesc/SuperHAsmBackend.h | 18 +-
.../MCTargetDesc/SuperHELFObjectWriter.cpp | 17 +-
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 68 ++--
llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp | 18 +-
llvm/lib/Target/SuperH/SuperHCallingConv.td | 4 +-
.../Target/SuperH/SuperHConstantPoolValue.cpp | 6 +-
.../Target/SuperH/SuperHConstantPoolValue.h | 1 -
.../Target/SuperH/SuperHFillDelaySlots.cpp | 2 +-
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 121 ++++---
llvm/lib/Target/SuperH/SuperHFrameLowering.h | 3 +-
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 75 ++---
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 298 +++++++++++++----
llvm/lib/Target/SuperH/SuperHISelLowering.h | 13 +-
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 18 ++
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 179 ++++++++++-
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 15 +
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 301 ++++++++++++------
llvm/lib/Target/SuperH/SuperHMCInstLower.cpp | 7 +-
.../SuperH/SuperHMachineFunctionInfo.cpp | 4 +-
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 37 ++-
llvm/lib/Target/SuperH/SuperHRegisterInfo.td | 40 ++-
22 files changed, 1001 insertions(+), 357 deletions(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index ae24d50d921b8..878d658f9e7f3 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -19,6 +19,7 @@
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/CommandLine.h"
@@ -29,14 +30,15 @@
#include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
+#include <optional>
using namespace llvm;
-SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
+SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) :
+ MCAsmBackend(STI.getTargetTriple().isLittleEndian()
? llvm::endianness::little
: llvm::endianness::big),
- STI(STI), OSABI(OSABI) {
-
+ STI(STI), OSABI(OSABI) {
}
bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
@@ -47,7 +49,7 @@ bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
// text section (otherwise we have unaligned instructions, and thus have
// far bigger problems), so just write NOP instructions.
uint64_t NumNops = Count / 2;
- for (uint64_t i = 0; i != NumNops; ++i)
+ for (uint64_t i = 0; i != NumNops; i++)
support::endian::write(OS, SHNopEnc, Endian);
// Write any straggling zeros needed.
@@ -129,47 +131,61 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
return Infos[Kind - FirstTargetFixupKind];
}
-void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
- const MCValue &Target, uint8_t *Data,
- uint64_t Value, bool IsResolved) {
-
- // Handle Relocations
- IsResolved = tryAddReloc(F, Fixup, Target, Value, IsResolved);
- MCFixupKind Kind = Fixup.getKind();
- if (mc::isRelocation(Kind))
- return;
+std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup &Fixup,
+ MCValue &Target, uint64_t &FixedValue) {
+ return {};
+}
- // Handle non-relocations
- MCContext &Ctx = getContext();
- MCFixupKindInfo Info = getFixupKindInfo(Kind);
- if (!Value)
- return; // No encoding change.
+unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t Value,
+ bool IsResolved, MCContext &Ctx,
+ const MCSubtargetInfo *STI) const {
+ unsigned Kind = Fixup.getKind();
+ int64_t Addend = Target.getConstant();
- unsigned NumBits = Info.TargetSize + Info.TargetOffset;
- unsigned NumBytes = (NumBits / 8) + ((NumBits % 8) == 0 ? 0 : 1);
- assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
- "Invalid fixup offset!");
+ switch (Kind) {
+ default:
+ return Value;
- // Flip the bits if neccesary, then spit them out
- Value <<= Info.TargetOffset;
- bool SwapValue = Endian == llvm::endianness::big;
- for (unsigned i = 0; i < NumBytes; ++i) {
- unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
- uint8_t mask = (((Value >> (i * 8)) & 0xff));
- Data[Idx] |= mask;
+ case SH::fixup_got_low16:
+ return (Value+Addend) & 65535;
+
+ case SH::fixup_got_medlow16:
+ return ((Value+Addend) >> 16) & 65535;
+
+ case SH::fixup_got_medhi16:
+ return ((Value+Addend) >> 32) & 65535;
+
+ case SH::fixup_got_hi16:
+ return ((Value+Addend) >> 48) & 65535;
+
+ case SH::fixup_got10by4:
+ return (Value+Addend) / 4;
+
+ case SH::fixup_got10by8:
+ return (Value+Addend) / 8;
+
+ case SH::fixup_relative:
+ case SH::fixup_relative64:
+ return Value+Addend;
+
+ case SH::fixup_dir32:
+ return (Value+Addend);
+
+ case SH::fixup_rel32:
+ return Value+Addend;
}
}
bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target, uint64_t &FixedValue,
bool IsResolved) {
-
MCValue PCITarget; // PC-Indirect Target
// Get indirect target location.
switch(Fixup.getKind()) {
default:
- return {};
+ return false;
case FK_Data_1:
case FK_Data_2:
@@ -186,7 +202,7 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
if (!PCITarget.getAddSym())
return false;
- // Evaluate as ELF.
+ // Evaluate addend as ELF.
auto &SA = static_cast<const MCSymbolELF &>(*PCITarget.getAddSym());
if (SA.isUndefined())
return false;
@@ -209,6 +225,39 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
return true;
}
+void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
+ const MCValue &Target, uint8_t *Data,
+ uint64_t Value, bool IsResolved) {
+
+ // Handle Relocations
+ IsResolved = tryAddReloc(F, Fixup, Target, Value, IsResolved);
+ MCFixupKind Kind = Fixup.getKind();
+ if (mc::isRelocation(Kind))
+ return;
+
+ // Handle non-relocations
+ MCContext &Ctx = getContext();
+ MCFixupKindInfo Info = getFixupKindInfo(Kind);
+ Value = adjustFixupValue(*Asm, Fixup, Target, Value, IsResolved,
+ Ctx, getSubtargetInfo(F));
+
+ if (!Value)
+ return; // No encoding change.
+
+ unsigned NumBits = Info.TargetSize + Info.TargetOffset;
+ unsigned NumBytes = (NumBits / 8) + ((NumBits % 8) == 0 ? 0 : 1);
+ assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
+ "Invalid fixup offset!");
+
+ // Flip the bits if neccesary, then spit them out
+ Value <<= Info.TargetOffset;
+ bool SwapValue = Endian == llvm::endianness::big;
+ for (unsigned i = 0; i < NumBytes; ++i) {
+ unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
+ Data[Idx] |= uint8_t(((Value >> (i * 8)) & 0xff));
+ }
+}
+
std::unique_ptr<MCObjectTargetWriter>
SuperHAsmBackend::createObjectTargetWriter() const {
return createSuperHELFObjectWriter(OSABI);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
index f27ed3891217b..833e1247b152a 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
@@ -31,17 +31,27 @@ class SuperHAsmBackend : public MCAsmBackend {
std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
+
void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
uint8_t *Data, uint64_t Value, bool IsResolved) override;
- bool tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
- const MCValue &Target, uint64_t &FixedValue,
- bool IsResolved);
+ std::optional<bool> evaluateFixup(const MCFragment &, MCFixup &, MCValue &,
+ uint64_t &) override;
std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const override;
-
+
bool writeNopData(raw_ostream &OS, uint64_t Count,
const MCSubtargetInfo *STI) const override;
+
+
+ bool tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t &FixedValue,
+ bool IsResolved);
+
+ unsigned adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t Value,
+ bool IsResolved, MCContext &Ctx,
+ const MCSubtargetInfo *STI) const;
};
} // namespace llvm
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index 20c6718e399ce..292d55241e814 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -50,9 +50,19 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
switch ((unsigned)Fixup.getKind()) {
case FK_Data_1:
case FK_Data_2:
- case FK_Data_4:
case FK_Data_8:
- return ELF::R_SH_NONE;
+ return 0;
+
+ case FK_Data_4: {
+ switch (Spec) {
+ case SH::S_None:
+ return ELF::R_SH_DIR32;
+ case SH::S_PCREL:
+ return ELF::R_SH_REL32;
+ default:
+ return SH::S_DIR;
+ }
+ }
case SH::fixup_got32:
return ELF::R_SH_GOT32;
@@ -172,7 +182,8 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
unsigned Type) const {
- return true;
+
+ return false;
}
std::unique_ptr<MCObjectTargetWriter>
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 55383441344a5..8d6c613eef9bf 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -12,15 +12,14 @@
#include "SuperHFixupKinds.h"
-#include "SuperHMCAsmInfo.h"
#include "SuperHMCTargetDesc.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/bit.h"
-#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
@@ -30,15 +29,14 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/DebugLog.h"
#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/ErrorHandling.h"
#include <cstdint>
using namespace llvm;
-#define DEBUG_TYPE "mccodeemitter"
+#define DEBUG_TYPE "sh-mccodeemitter"
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
@@ -70,11 +68,15 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
- unsigned getBranchTargetOpValue(const MCInst &MI, const MCExpr *Expr,
+ unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
- unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
+ unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ unsigned getPCRelOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -122,7 +124,6 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
-
uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
// NOTE: All base instructions are 16-bit in SH ASM
@@ -141,11 +142,16 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
++MCNumEmitted;
}
-unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI,
- const MCExpr *Expr,
+unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
- return getExprOpValue(MI, Expr, Fixups, STI);
+ return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
+}
+
+unsigned SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
}
unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
@@ -156,13 +162,21 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
MCExpr::ExprKind Kind = Expr->getKind();
- // Binary Op
- if (Kind == MCExpr::Binary) {
- Expr = static_cast<const MCBinaryExpr *>(Expr)->getLHS();
- Kind = Expr->getKind();
+ switch(Kind) {
+ case MCExpr::ExprKind::Binary: {
+ unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI);
+ Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI);
+ return Res;
}
-
- if (Kind == MCExpr::SymbolRef) {
+ case MCExpr::ExprKind::Target: {
+ llvm_unreachable("TODO");
+ }
+ case MCExpr::ExprKind::Specifier: {
+ const MCSpecifierExpr *Spec = static_cast<const MCSpecifierExpr *>(Expr);
+ Fixups.push_back(MCFixup::create(0, Spec, Spec->getSpecifier()));
+ return 0;
+ }
+ case MCExpr::ExprKind::SymbolRef: {
// NOTE: A few (DSP and SH2A) instructions are 32-bits wide.
// We handle those quite crudely.
@@ -170,21 +184,23 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
Fixups.push_back(MCFixup::create(0, Expr, isOpcode32(OpCode) ? FK_Data_4 : FK_Data_2, true));
return 0;
}
-
- // Constant immediate.
- int64_t Result;
- if (Expr->evaluateAsAbsolute(Result))
- return Result;
-
- return 0;
+ case MCExpr::ExprKind::Constant: {
+ const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
+ return Const->getValue();
+ }
+ default:
+ llvm_unreachable("expression not supported!");
+ }
}
+/// getMachineOpValue - Return binary encoding of operand. If the machine
+/// operand requires relocation, record the relocation and return zero.
unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI,
const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
if (MO.isReg())
- return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
+ return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
if (MO.isImm())
return MO.getImm();
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index d3dc1cad8ba3f..567fcc79a3e0d 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -21,6 +21,7 @@
#include "SuperHMCInstLower.h"
#include "TargetInfo/SuperHTargetInfo.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/TargetRegistry.h"
@@ -96,14 +97,16 @@ bool SuperHAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Convert a SuperH-specific constant pool modifier into the associated
// specifier.
-static uint8_t getSpecifierFromModifier(SHCP::SHCPModifier Modifier) {
+static uint8_t getModifierSpecifier(SHCP::SHCPModifier Modifier) {
switch (Modifier) {
- case SHCP::SHCPModifier::DIR:
- case SHCP::SHCPModifier::no_modifier:
- return SHII::MO_DIR;
- default:
- return SHII::MO_DIR;
+ case SHCP::no_modifier:
+ return SH::S_DIR;
+ case SHCP::GOT_PCREL:
+ return SH::S_GOT_PCREL;
+ case SHCP::DIR:
+ return SH::S_DIR;
}
+ llvm_unreachable("Invalid SHCPModifier!");
}
@@ -173,7 +176,6 @@ bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned Op
// Constant Pool
//===----------------------------------------------------------------------===//
-
void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
const DataLayout &DL = getDataLayout();
int Size = DL.getTypeAllocSize(MCPV->getType());
@@ -197,7 +199,7 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
// Create an MCSymbol for the reference.
const MCExpr *Expr = MCSymbolRefExpr::create(
- MCSym,
+ MCSym,
OutContext
);
OutStreamer->emitValue(Expr, Size);
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index 429bd8be41908..71d899d3c7e8b 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -15,7 +15,7 @@
def CC_SH : CallingConv<[
// All lower size parameters are promoted to 32-bit
- CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+ CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
]>;
@@ -29,7 +29,7 @@ def RetCC_SH : CallingConv<[
// Anything that doesn't fit in registers should be spilled.
CCIfType<[i32], CCAssignToStack<4, 4>>,
- CCIfType<[i64], CCAssignToStack<8, 8>>,
+ CCIfType<[i64], CCAssignToStack<8, 4>>,
]>;
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
index 0b9d5eaf0701d..cdedd3e8f634b 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
@@ -40,9 +40,7 @@ StringRef SuperHConstantPoolValue::getModifierText() const {
case SHCP::no_modifier:
return "none";
case SHCP::GOT_PCREL:
- return "GOT_PCREL";
- case SHCP::GOT_PLTOFF:
- return "gotpltoff";
+ return "gotpcrel";
case SHCP::DIR:
return "";
}
@@ -199,7 +197,7 @@ SuperHConstantPoolSymbol::SuperHConstantPoolSymbol(LLVMContext &C, StringRef s,
SuperHConstantPoolSymbol *SuperHConstantPoolSymbol::Create(LLVMContext &C,
StringRef s, unsigned ID) {
- return new SuperHConstantPoolSymbol(C, s, ID, SHCP::no_modifier);
+ return new SuperHConstantPoolSymbol(C, s, ID, SHCP::DIR);
}
int SuperHConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
index f606b1b6869b5..86f718ca381ce 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
@@ -41,7 +41,6 @@ namespace SHCP {
no_modifier, /// None
DIR, /// Direct
GOT_PCREL, /// Global Offset Table, PC Relative
- GOT_PLTOFF, /// Global Offset Table, Thread Pointer Offset
};
} // end namespace SHCP
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 8d092e0b570aa..10510a3e13183 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -114,7 +114,7 @@ bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
MachineFunction &MF = *MBB.getParent();
MachineInstr &MI = *MBBI;
- if (auto *Candidate = SuperHFillDelaySlots::findSlotCandidate(MBB, MBBI)) {
+ if (auto *Candidate = findSlotCandidate(MBB, MBBI)) {
LLVM_DEBUG(dbgs() << "Swapping " << TII->getName(MI.getOpcode())
<< " and " << TII->getName(Candidate->getOpcode())
<< " @ " << MBB.getParent()->getName() << "\n");
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 93baa923182da..e4341a2d59db7 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -26,6 +26,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugLog.h"
#include "llvm/Target/TargetMachine.h"
+#include <cstdint>
#define DEBUG_TYPE "sh-framelowering"
@@ -58,16 +59,30 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
return false;
Register SP = RII.getStackRegister();
+ Register FP = RII.getFrameRegister();
- if (AdjValue < 255) {
+ if (abs(AdjValue) < 255) {
- // Fast path, emit a single immediate add.
- // Emit add #-(size),r15
- BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
- .addReg(SP)
- .addImm((int)AdjValue);
+ if (AdjValue < 0) {
+
+ // Fast path, emit a single immediate add.
+ // Emit add #-(size),r15
+ BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
+ .addReg(SP)
+ .addImm((int)AdjValue);
+ return true;
+ }
+
+ if (AdjValue > 0) {
+
+ // Fast path, emit a single immediate add.
+ // Emit add #(size),r14
+ BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), FP)
+ .addReg(FP)
+ .addImm((int)AdjValue);
+ return true;
+ }
- return true;
}
// Slow path, shift 8 bits at a time into r0.
@@ -115,67 +130,48 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
const MCContext &Ctx = MF.getContext();
DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
- bool HasFP = hasFP(MF);
Register SP = RII.getStackRegister();
Register FP = RII.getFrameRegister();
Register GOT = RII.getGOTRegister();
+ LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
+
// Early exit if we have no frame pointer.
- if (!HasFP) {
+ if (!hasFP(MF)) {
return;
}
- // Realign stack
+ // Realign stack to 32-bit offsets.
uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
MFI.setStackSize(StackSize);
+ // Store GOT
if (STI.isPositionIndependent()) {
- // Position Independent Prologue
-
- // 1. Store GOT to stack and load local GOT.
if (auto *GOTSym = MF.getPICBaseSymbol()) {
BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
.addReg(GOT)
.setMIFlag(MachineInstr::FrameSetup);
}
+ }
- // 2. Establish Stack Frame
- // mov.l r14, at -r15
- // add <stackadj>,r15
- // mov r15,r14
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), FP)
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameSetup);
- emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), SP)
- .addReg(FP)
- .setMIFlag(MachineInstr::FrameSetup);
-
- // 4. Save return address to stack.
- if (MFI.hasCalls()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameSetup);
- }
-
- } else {
- // Position Dependent Prologue
+ // Establish Stack Frame
+ // mov.l r14, at -r15
+ // add <stackadj>,r15
+ // mov r15,r14
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+ .addReg(FP)
+ .setMIFlag(MachineInstr::FrameSetup);
+ emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
- // 1. Establish Frame Pointer
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
- .addReg(FP)
+ // Save return address to stack.
+ if (MFI.hasCalls()) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+ .addReg(SP)
.setMIFlag(MachineInstr::FrameSetup);
-
- // 2. Create new stack frame
- emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
-
- // 3. Save return address to stack.
- if (MFI.hasCalls()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameSetup);
- }
}
}
@@ -184,6 +180,8 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
Register SP = RII.getStackRegister();
Register FP = RII.getFrameRegister();
+ LLVM_DEBUG(dbgs() << "Emitting epilogue...\n");
+
// Early exit if we have no frame pointer.
if (!hasFP(MF)) {
return;
@@ -207,8 +205,15 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
}
// 2. Delete stack frame, restoring stack pointer.
- if (StackSize > 0)
+ if (StackSize > 0) {
emitSPAdj(MF, MBB, MBBI, StackSize);
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRminciRn), SP)
+ .addReg(FP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ }
} else {
@@ -220,13 +225,24 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
}
// 2. Delete stack frame, restoring stack pointer.
- if (StackSize > 0)
+ // add <stackadj>,r14
+ // mov r14,r15
+ // mov.l @r15+,r14
+ if (StackSize > 0) {
emitSPAdj(MF, MBB, MBBI, StackSize);
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRminciRn), SP)
+ .addReg(FP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ }
}
}
bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+ LLVM_DEBUG(dbgs() << "Spilling " << CSI.size() << " registers...\n");
if (CSI.empty()) {
return false;
}
@@ -251,6 +267,7 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+ LLVM_DEBUG(dbgs() << "Restoring " << CSI.size() << " registers...\n");
if (CSI.empty()) {
return false;
}
@@ -262,7 +279,9 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
const TargetInstrInfo &TII = *STI.getInstrInfo();
Register SP = RII.getStackRegister();
- for (const CalleeSavedInfo &I : CSI) {
+
+ for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
+
MCRegister Reg = I.getReg();
BuildMI(MBB, MI, DL, TII.get(SH::MOVLRminciRn), SP)
.addReg(Reg)
@@ -316,7 +335,7 @@ bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
- return !MFI.hasVarSizedObjects();
+ return hasFP(MF) && !MFI.hasVarSizedObjects();
}
void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index 7a20234e7817c..66c3ff6eb6dce 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -29,7 +29,8 @@ class SuperHFrameLowering : public TargetFrameLowering {
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
/*StackAlignment*/Align(4),
/*LocalAreaOffset*/0,
- /*TransAl*/Align(4)),
+ /*TransAl*/Align(4),
+ /*StackReal*/false),
STI(STI) {}
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
bool hasReservedCallFrame(const MachineFunction &MF) const override;
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 3b9e745b8d334..613e23fccb2d6 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -75,7 +75,7 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
InlineAsm::ConstraintCode ConstraintCode,
std::vector<SDValue> &OutOps) override;
- bool SelectAddr(SDNode *Root, SDValue N, SDValue &Base, SDValue &Disp);
+ bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
/// Return a target constant with the specified value of type i4.
@@ -107,7 +107,7 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
bool trySelectFrameIndex(SDNode *N);
bool trySelectWrapper(SDNode *N);
bool trySelectCMP(SDNode *N);
- bool trySelectBrcond(SDNode *N);
+ bool trySelectBRCOND(SDNode *N);
bool trySelectSELECT_CC(SDNode *N);
const SuperHSubtarget *Subtarget;
@@ -136,6 +136,23 @@ bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
return false;
}
+bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
+ SDValue &Disp) {
+ SDLoc dl(Op);
+ auto DL = CurDAG->getDataLayout();
+ MVT PtrVT = getTargetLowering()->getPointerTy(DL);
+
+ // if the address is a frame index get the TargetFrameIndex.
+ if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
+ Disp = CurDAG->getTargetConstant(0, dl, MVT::i8);
+
+ return true;
+ }
+
+ return false;
+}
+
@@ -151,26 +168,26 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
SDValue N0 = N->getOperand(0);
- // Global Addresses
- if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
- SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+ // External Symbols
+ if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
ReplaceNode(N, Res);
return true;
}
- // External Symbols
- if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
- SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+ // Global Addresses
+ if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
ReplaceNode(N, Res);
return true;
}
// Block Addresses
if (auto *CPV = SFI->tryGetConstant((BlockAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
- SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
ReplaceNode(N, Res);
return true;
}
@@ -202,31 +219,31 @@ bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
// TST would be faster in this case.
if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
if (C->getSExtValue() == 0) {
- Res = CurDAG->getMachineNode(SH::TSTRmRn, DL, MVT::i32, LHS, LHS);
+ Res = CurDAG->getMachineNode(SH::TSTRmRn, DL, MVT::Glue, LHS, LHS);
break;
}
}
- Res = CurDAG->getMachineNode(SH::CMPEQRmRn, DL, MVT::i32, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPEQRmRn, DL, MVT::Glue, LHS, RHS);
break;
}
case ISD::SETUGE:
case ISD::SETULT: {
- Res = CurDAG->getMachineNode(SH::CMPHSRmRn, DL, MVT::i32, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPHSRmRn, DL, MVT::Glue, LHS, RHS);
break;
}
case ISD::SETOGE:
case ISD::SETOLT: {
- Res = CurDAG->getMachineNode(SH::CMPGERmRn, DL, MVT::i32, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPGERmRn, DL, MVT::Glue, LHS, RHS);
break;
}
case ISD::SETUGT:
case ISD::SETULE: {
- Res = CurDAG->getMachineNode(SH::CMPGTRmRn, DL, MVT::i32, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPGTRmRn, DL, MVT::Glue, LHS, RHS);
break;
}
case ISD::SETOGT:
case ISD::SETOLE: {
- Res = CurDAG->getMachineNode(SH::CMPHIRmRn, DL, MVT::i32, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPHIRmRn, DL, MVT::Glue, LHS, RHS);
break;
}
}
@@ -240,18 +257,13 @@ bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
return false;
}
-bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
+bool SuperHDAGToDAGISel::trySelectBRCOND(SDNode *N) {
SDValue Chain = N->getOperand(0);
SDValue Dest = N->getOperand(1);
ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
SDValue Cmp = N->getOperand(3);
SDLoc DL(N);
- // NOTE: The CMP instruction writes implicitly to the T bit of the status
- // register, as such, we need to add said copy to our chain to ensure
- // scheduling can handle it.
- Chain = CurDAG->getCopyToReg(Chain, DL, SH::SR, Cmp, SDValue());
-
// NOTE: The comparisons just set the T bit, it's up to later instructions
// to interpret the T bit as positive or negative.
MachineSDNode *Res = nullptr;
@@ -263,7 +275,7 @@ bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
case ISD::SETUGT:
case ISD::SETOGT:
Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BTS : SH::BT,
- DL, MVT::Other, Dest, Chain);
+ DL, MVT::Other, Dest, Chain, Cmp);
break;
case ISD::SETNE:
case ISD::SETULE:
@@ -271,7 +283,7 @@ bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
case ISD::SETULT:
case ISD::SETOLT:
Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BFS : SH::BF,
- DL, MVT::Other, Dest, Chain);
+ DL, MVT::Other, Dest, Chain, Cmp);
break;
}
@@ -284,13 +296,6 @@ bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
return false;
}
-bool SuperHDAGToDAGISel::trySelectSELECT_CC(SDNode *N) {
- const SDValue &TrueV = N->getOperand(0);
- const SDValue &FalseV = N->getOperand(1);
- ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
- const SDValue &Cmp = N->getOperand(3);
- return false;
-}
@@ -336,10 +341,8 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
return trySelectWrapper(N);
case SHISD::CMP:
return trySelectCMP(N);
- case SHISD::SELECT_CC:
- return trySelectSELECT_CC(N);
case SHISD::BRCOND:
- return trySelectBrcond(N);
+ return trySelectBRCOND(N);
default:
return false;
}
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 252bb5952524d..299285b73c5c4 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -13,6 +13,7 @@
#include "SuperHISelLowering.h"
#include "SuperHConstantPoolValue.h"
+#include "SuperHInstrInfo.h"
#include "SuperHMachineFunctionInfo.h"
#include "SuperHSelectionDAGInfo.h"
#include "MCTargetDesc/SuperHMCTargetDesc.h"
@@ -24,18 +25,21 @@
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DebugLog.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
#define DEBUG_TYPE "sh-lower"
-#define DEBUG_FN_PRINT() LDBG() << __PRETTY_FUNCTION__;
+#define DEBUG_FN_PRINT() LLVM_DEBUG(dbgs() << " - " << __PRETTY_FUNCTION__ << "\n");
static bool RetCC_SuperH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
@@ -71,8 +75,11 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setLoadExtAction(N, VT, MVT::i1, Promote);
setLoadExtAction(N, VT, MVT::i64, Expand);
}
+
+ setTruncStoreAction(VT, MVT::i1, Promote);
}
+
// Division and remainders are multi-instruction sequences
// on SuperH. Use a custom pass to lower those.
for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
@@ -109,6 +116,13 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setMinFunctionAlignment(Align(4));
}
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+// LOWERING
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+
@@ -116,9 +130,8 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
// CONDITIONAL BRANCH LOWERING
//===----------------------------------------------------------------------===//
SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
- SDValue &OutCC, SelectionDAG &DAG, SDLoc DL) const {
- OutCC = DAG.getCondCode(CC);
- return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, OutCC);
+ SelectionDAG &DAG, SDLoc DL) const {
+ return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, DAG.getCondCode(CC));
}
SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
@@ -129,12 +142,11 @@ SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) cons
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
SDLoc DL(Op);
- SDValue TargetCC;
- SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+ SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
+ SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i8);
SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
return DAG.getNode(SHISD::SELECT_CC, DL, Op.getValueType(), Ops);
-
}
SDValue SuperHTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
@@ -143,8 +155,8 @@ SDValue SuperHTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
SDLoc DL(Op);
- SDValue TargetCC;
- SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+ SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
+ SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i8);
SDValue TrueV = DAG.getConstant(1, DL, Op.getValueType());
SDValue FalseV = DAG.getConstant(0, DL, Op.getValueType());
@@ -162,8 +174,9 @@ SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
SDValue Dest = Op.getOperand(4);
SDLoc DL(Op);
- SDValue TargetCC;
- SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+ SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
+ SDValue TargetCC = DAG.getCondCode(CC);
+
return DAG.getNode(SHISD::BRCOND, DL, MVT::Other, Chain, Dest, TargetCC, Cmp);
}
@@ -182,8 +195,8 @@ SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
auto PtrVT = getPointerTy(DAG.getDataLayout());
auto DL = SDLoc(G);
- SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
- SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, OpFlags);
+ // SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
+ SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0);
return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
}
return SDValue();
@@ -200,7 +213,7 @@ SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG)
const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
- SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags);
+ SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT);
return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
}
return SDValue();
@@ -217,7 +230,7 @@ SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) c
const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
- SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT, OpFlags);
+ SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT);
return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
}
return SDValue();
@@ -246,30 +259,55 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CC_SH);
- unsigned InIdx = 0;
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
- CCValAssign &VA = ArgLocs[i];
- SDValue Arg;
-
+
+ SDValue ArgValue;
+ for (CCValAssign &VA : ArgLocs) {
+
+ // Arguments stored on registers.
if (VA.isRegLoc()) {
- Register VReg = RegInfo.createVirtualRegister(&SH::GPRRegClass);
- MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
- Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
- if (VA.getLocInfo() != CCValAssign::Indirect) {
- if (VA.getLocVT() == MVT::f32)
- Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
- else if (VA.getLocVT() != MVT::i32) {
- Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
- DAG.getValueType(VA.getLocVT()));
- Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
- }
- InVals.push_back(Arg);
- continue;
+ EVT RegVT = VA.getLocVT();
+ const TargetRegisterClass *RC;
+ if (RegVT == MVT::i8) {
+ RC = &SH::GPRRegClass;
+ } else if (RegVT == MVT::i16) {
+ RC = &SH::GPRRegClass;
+ } else if (RegVT == MVT::i32) {
+ RC = &SH::GPRRegClass;
+ } else {
+ llvm_unreachable("Unknown argument type!");
}
+
+ Register Reg = MF.addLiveIn(VA.getLocReg(), RC);
+ ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
+
+ // NOTE: Clang should not promote any i8 or i16 to i32 but for safety the
+ // following code will handle zexts or sexts generated by other
+ // front ends. Otherwise:
+ switch (VA.getLocInfo()) {
+ default:
+ llvm_unreachable("Unknown loc info!");
+ case CCValAssign::Full:
+ break;
+ case CCValAssign::BCvt:
+ ArgValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), ArgValue);
+ break;
+ case CCValAssign::SExt:
+ ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,
+ DAG.getValueType(VA.getValVT()));
+ ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
+ break;
+ case CCValAssign::ZExt:
+ ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,
+ DAG.getValueType(VA.getValVT()));
+ ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
+ break;
+ }
+
+ InVals.push_back(ArgValue);
} else {
- // Try matching frame index.
- assert(VA.isMemLoc());
+ // Only arguments passed on the stack should make it here.
+ assert(VA.isMemLoc());
EVT LocVT = VA.getLocVT();
// Create the frame index object for this incoming parameter.
@@ -281,27 +319,13 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DL));
InVals.push_back(DAG.getLoad(LocVT, dl, Chain, FIN,
MachinePointerInfo::getFixedStack(MF, FI)));
-
- }
-
- SDValue ArgValue =
- DAG.getLoad(VA.getValVT(), dl, Chain, Arg, MachinePointerInfo());
- InVals.push_back(ArgValue);
-
- unsigned ArgIndex = Ins[InIdx].OrigArgIndex;
- assert(Ins[InIdx].PartOffset == 0);
- while (i + 1 != e && Ins[InIdx + 1].OrigArgIndex == ArgIndex) {
- CCValAssign &PartVA = ArgLocs[i + 1];
- unsigned PartOffset = Ins[InIdx + 1].PartOffset;
- SDValue Address = DAG.getMemBasePlusOffset(
- ArgValue, TypeSize::getFixed(PartOffset), dl);
- InVals.push_back(DAG.getLoad(PartVA.getValVT(), dl, Chain, Address,
- MachinePointerInfo()));
- ++i;
- ++InIdx;
}
}
+ // TODO: Handle varargs.
+ if (IsVarArg) {
+ llvm_unreachable("varargs are not yet supported!");
+ }
return Chain;
}
@@ -616,12 +640,172 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
return LowerExternalSymbol(Op, DAG);
case ISD::BlockAddress:
return LowerBlockAddress(Op, DAG);
- case ISD::SETCC:
- return LowerBR_CC(Op, DAG);
- case ISD::SELECT_CC:
- return LowerBR_CC(Op, DAG);
case ISD::BR_CC:
return LowerBR_CC(Op, DAG);
+ case ISD::SETCC:
+ return LowerSETCC(Op, DAG);
+ case ISD::SELECT_CC:
+ return LowerSELECT_CC(Op, DAG);
}
return SDValue();
+}
+
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+// INSERTERS
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Load/Store Lowering
+//===----------------------------------------------------------------------===//
+
+MachineBasicBlock *SuperHTargetLowering::insertLoad(MachineInstr &MI,
+ MachineBasicBlock *MBB) const {
+ DEBUG_FN_PRINT()
+ MachineFunction &MF = *MBB->getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+ const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
+
+ MachineOperand Dest = MI.getOperand(0);
+ MachineOperand Offset = MI.getOperand(1);
+
+ // Target index load.
+ if (Dest.isTargetIndex()) {
+
+ }
+
+ MI.eraseFromParent();
+ return MBB;
+}
+
+MachineBasicBlock *SuperHTargetLowering::insertStore(MachineInstr &MI,
+ MachineBasicBlock *MBB) const {
+ DEBUG_FN_PRINT()
+
+ MI.eraseFromParent();
+ return MBB;
+}
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+// SelectCC/SetCC Lowering
+//===----------------------------------------------------------------------===//
+
+MachineBasicBlock *SuperHTargetLowering::insertSELECTCC(MachineInstr &MI,
+ MachineBasicBlock *MBB) const {
+ DEBUG_FN_PRINT()
+
+ MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
+ const SuperHInstrInfo &TII = *Subtarget->getInstrInfo();
+ MachineBasicBlock::iterator BBI(MI);
+ DebugLoc DL = MI.getDebugLoc();
+
+ MachineOperand TrueV = MI.getOperand(0);
+ MachineOperand FalseV = MI.getOperand(1);
+ ISD::CondCode CC = (ISD::CondCode)MI.getOperand(3).getImm();
+
+ // Lower True-False selection
+ if (TrueV.isImm() && FalseV.isImm()) {
+ if (TrueV.getImm() == 1 && FalseV.getImm() == 0) {
+ BuildMI(*MBB, BBI, DL, TII.get(SH::MOVTRn), SH::R0);
+ MI.eraseFromParent();
+ return MBB;
+ }
+ }
+
+ // To "insert" a SELECT instruction, we insert the diamond
+ // control-flow pattern. The incoming instruction knows the
+ // destination vreg to set, the condition code register to branch
+ // on, the true/false values to select between, and a branch opcode
+ // to use.
+
+ MachineFunction *MF = MBB->getParent();
+ const BasicBlock *LLVM_BB = MBB->getBasicBlock();
+ MachineBasicBlock *FallThrough = MBB->getFallThrough();
+
+ // If the current basic block falls through to another basic block,
+ // we must insert an unconditional branch to the fallthrough destination
+ // if we are to insert basic blocks at the prior fallthrough point.
+ if (FallThrough != nullptr) {
+ BuildMI(MBB, DL, TII.get(SH::BRA)).addMBB(FallThrough);
+ }
+
+ MachineBasicBlock *trueMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *falseMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+
+ MachineFunction::iterator I;
+ for (I = MF->begin(); I != MF->end() && &(*I) != MBB; ++I)
+ ;
+ if (I != MF->end())
+ ++I;
+ MF->insert(I, trueMBB);
+ MF->insert(I, falseMBB);
+
+ // Set the call frame size on entry to the new basic blocks.
+ unsigned CallFrameSize = TII.getCallFrameSizeAt(MI);
+ trueMBB->setCallFrameSize(CallFrameSize);
+ falseMBB->setCallFrameSize(CallFrameSize);
+
+ // Transfer remaining instructions and all successors of the current
+ // block to the block which will contain the Phi node for the
+ // select.
+ trueMBB->splice(trueMBB->begin(), MBB,
+ std::next(MachineBasicBlock::iterator(MI)), MBB->end());
+ trueMBB->transferSuccessorsAndUpdatePHIs(MBB);
+
+ BuildMI(MBB, DL, TII.getBrCond(CC)).addMBB(trueMBB);
+ BuildMI(MBB, DL, TII.get(SH::BRA)).addMBB(falseMBB);
+ MBB->addSuccessor(falseMBB);
+ MBB->addSuccessor(trueMBB);
+
+ // Unconditionally flow back to the true block
+ BuildMI(falseMBB, DL, TII.get(SH::BRA)).addMBB(trueMBB);
+ falseMBB->addSuccessor(trueMBB);
+
+ // Set up the Phi node to determine where we came from
+ BuildMI(*trueMBB, trueMBB->begin(), DL, TII.get(SH::PHI),
+ MI.getOperand(0).getReg())
+ .addReg(MI.getOperand(1).getReg())
+ .addMBB(MBB)
+ .addReg(MI.getOperand(2).getReg())
+ .addMBB(falseMBB);
+
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
+ return trueMBB;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// CUSTOM LOWERING
+//===----------------------------------------------------------------------===//
+
+MachineBasicBlock *
+SuperHTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
+ MachineBasicBlock *MBB) const {
+ int Op = MI.getOpcode();
+
+ switch (Op) {
+ default: break;
+ case SH::Select8:
+ case SH::Select16:
+ case SH::Select32:
+ return insertSELECTCC(MI, MBB);
+ case SH::LDI8:
+ case SH::LDI16:
+ case SH::LDI32:
+ return insertLoad(MI, MBB);
+ case SH::STI8:
+ case SH::STI16:
+ case SH::STI32:
+ return insertStore(MI, MBB);
+ }
+
+ return MBB;
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index ffdc90b53afc1..6f761b167f98e 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -70,9 +70,20 @@ class SuperHTargetLowering : public TargetLowering {
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
- SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &OutCC,
+ SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
SelectionDAG &DAG, SDLoc DL) const;
+
+ // Inserters
+ MachineBasicBlock *
+ EmitInstrWithCustomInserter(MachineInstr &MI,
+ MachineBasicBlock *MBB) const override;
private:
+ MachineBasicBlock *insertSELECTCC(MachineInstr &MI,
+ MachineBasicBlock *BB) const;
+ MachineBasicBlock *insertLoad(MachineInstr &MI,
+ MachineBasicBlock *BB) const;
+ MachineBasicBlock *insertStore(MachineInstr &MI,
+ MachineBasicBlock *BB) const;
SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index 1c2e6e03f6b3c..e8624d62397e5 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -74,10 +74,28 @@ class SHInst32<dag outs, dag ins, string asmstr, list<dag> pattern = []>
// in later passes implemented in C++.
class SHPseudo<dag outs, dag ins, string asmstr="; error: this should not be emitted", list<dag> pattern = []>
: SHInst<outs, ins, asmstr, pattern> {
+ let Pattern = pattern;
+
let isCodeGenOnly = 1;
let isPseudo = 1;
}
+class SHSelectPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : SHPseudo<outs, ins, asmstr, pattern> {
+ let usesCustomInserter = 1;
+ let Uses = [SR];
+}
+
+class SHLoadPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : SHPseudo<outs, ins, asmstr, pattern> {
+ let usesCustomInserter = 1;
+}
+
+class SHStorePseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : SHPseudo<outs, ins, asmstr, pattern> {
+ let usesCustomInserter = 1;
+}
+
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index e27b09e12fd4f..2b24bd6372234 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -18,11 +18,11 @@
#include "MCTargetDesc/SuperHInstPrinter.h"
#include "SuperH.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
@@ -42,6 +42,8 @@ SuperHInstrInfo::SuperHInstrInfo(const SuperHSubtarget &ST)
: SuperHGenInstrInfo(ST, RI, SH::ADJCALLSTACKDOWN, SH::ADJCALLSTACKUP),
RI(ST), Subtarget(ST) { }
+// Pin the vtable to this file.
+void SuperHInstrInfo::anchor() {}
// Gets whether a given opcode can fill a delay slot.
@@ -99,8 +101,14 @@ const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
default:
llvm_unreachable("Unknown condition code!");
case ISD::SETTRUE:
+ case ISD::SETEQ:
+ case ISD::SETGT:
+ case ISD::SETGE:
return get(SH::BT);
case ISD::SETFALSE:
+ case ISD::SETNE:
+ case ISD::SETLT:
+ case ISD::SETLE:
return get(SH::BF);
}
}
@@ -134,6 +142,140 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
llvm_unreachable("Impossible reg-to-reg copy");
}
+void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ Register SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC, Register VReg,
+ MachineInstr::MIFlag Flags) const {
+ LLVM_DEBUG(dbgs() << "Store " << RI.getName(SrcReg) << " to slot " << FrameIndex << "\n");
+
+ MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+ const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
+ int64_t Offset = MFI.getObjectOffset(FrameIndex) +
+ MFI.getStackSize() -
+ TFI->getOffsetOfLocalArea();
+
+ // NOTE: R0-based displacement instructions have a different encoding
+ // from Rn based instructions, as such we need to know whether
+ // we need to copy the src register into R0 temporarily.
+ Register SrcStrReg;
+ unsigned Opcode = 0;
+ if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
+ Opcode = SH::MOVBR0D4Rni;
+ SrcStrReg = SH::R0;
+ } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
+ Opcode = SH::MOVWR0D4Rni;
+ SrcStrReg = SH::R0;
+ } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
+ Opcode = SH::MOVLRmD4Rni;
+ SrcStrReg = SrcReg;
+ } else {
+ llvm_unreachable("Cannot store this register into a stack slot!");
+ }
+
+ // mov r14,r1
+ // add #-<frame size>,r1
+ BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SH::R1)
+ .addReg(SH::R14);
+ BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI8Rn), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-(int)MFI.getStackSize());
+
+ // mov srcreg,r0
+ // mov.b/w r0,@(<offset>,r1)
+ if (SrcStrReg != SrcReg) {
+ BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SrcStrReg)
+ .addReg(SrcReg, getKillRegState(isKill));
+ BuildMI(MBB, MI, DebugLoc(), get(Opcode))
+ .addReg(SH::R1)
+ .addImm(Offset);
+ return;
+ }
+
+ // mov.l srcreg,@(<offset>,r1)
+ BuildMI(MBB, MI, DebugLoc(), get(Opcode))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addReg(SH::R1)
+ .addImm(Offset);
+}
+
+void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ Register DestReg, int FrameIndex,
+ const TargetRegisterClass *RC, Register VReg,
+ unsigned SubReg, MachineInstr::MIFlag Flags) const {
+ MachineFunction &MF = *MBB.getParent();
+ const SuperHRegisterInfo &RI = getRegisterInfo();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+ const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
+ int64_t Offset = MFI.getObjectOffset(FrameIndex) +
+ MFI.getStackSize() -
+ TFI->getOffsetOfLocalArea();
+
+ LLVM_DEBUG(dbgs() << "Load " << RI.getName(DestReg) << " from slot " << FrameIndex << "\n");
+
+ // NOTE: R0-based displacement instructions have a different encoding
+ // from Rn based instructions, as such we need to know whether
+ // we need to copy to our dst register from R0.
+ unsigned Opcode = 0;
+ Register DstStrReg;
+ if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
+ Opcode = SH::MOVBD4RmiR0;
+ DstStrReg = SH::R0;
+ } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
+ Opcode = SH::MOVWD4RmiR0;
+ DstStrReg = SH::R0;
+ } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
+ Opcode = SH::MOVLD4RmiRn;
+ DstStrReg = DestReg;
+ } else {
+ llvm_unreachable("Cannot load this register into a stack slot!");
+ }
+
+ // mov r14,r1
+ // add #-<frame size>,r1
+ BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SH::R1)
+ .addReg(SH::R14);
+ BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI8Rn), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-(int)MFI.getStackSize());
+
+ // mov.b/w @(<offset>,r1),r0
+ // mov r0,dstreg
+ if (DstStrReg != DestReg) {
+ BuildMI(MBB, MI, DebugLoc(), get(Opcode))
+ .addReg(SH::R1)
+ .addImm(Offset);
+ BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), DestReg)
+ .addReg(DstStrReg);
+ return;
+ }
+
+ // mov.l @(<offset>,r1),destreg
+ BuildMI(MBB, MI, DebugLoc(), get(Opcode), DestReg)
+ .addReg(SH::R1)
+ .addImm(Offset);
+}
+
+Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+ if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
+ MI.getOperand(2).getImm() == 0) {
+ FrameIndex = MI.getOperand(1).getIndex();
+ return MI.getOperand(0).getReg();
+ }
+ return 0;
+}
+
+Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+ if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
+ MI.getOperand(1).getImm() == 0) {
+ FrameIndex = MI.getOperand(0).getIndex();
+ return MI.getOperand(2).getReg();
+ }
+ return 0;
+}
+
@@ -226,25 +368,30 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
continue;
}
- // Handle subsequent conditional branches. Only handle the case where all
- // conditional branches branch to the same destination.
- assert(Cond.size() == 1);
- assert(TBB);
-
- // Only handle the case where all conditional branches branch to
- // the same destination.
- if (TBB != I->getOperand(0).getMBB()) {
- return true;
- }
+ FBB = TBB;
+ TBB = I->getOperand(0).getMBB();
+ Cond.push_back(MachineOperand::CreateImm(BranchCode));
+ continue;
+ }
- ISD::CondCode OldBranchCode = (ISD::CondCode)Cond[0].getImm();
- // If the conditions are the same, we can leave them alone.
- if (OldBranchCode == BranchCode) {
- continue;
- }
+ // Handle subsequent conditional branches. Only handle the case where all
+ // conditional branches branch to the same destination.
+ assert(Cond.size() == 1);
+ assert(TBB);
+ // Only handle the case where all conditional branches branch to
+ // the same destination.
+ if (TBB != I->getOperand(0).getMBB()) {
return true;
}
+
+ ISD::CondCode OldBranchCode = (ISD::CondCode)Cond[0].getImm();
+ // If the conditions are the same, we can leave them alone.
+ if (OldBranchCode == BranchCode) {
+ continue;
+ }
+
+ return true;
}
return false;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index da25ff9390727..2a73b55410f1a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -17,6 +17,7 @@
#include "SuperHRegisterInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
#define GET_INSTRINFO_HEADER
#include "SuperHGenInstrInfo.inc"
@@ -26,6 +27,7 @@ namespace llvm {
class SuperHInstrInfo : public SuperHGenInstrInfo {
const SuperHRegisterInfo RI;
const SuperHSubtarget &Subtarget;
+ virtual void anchor();
public:
explicit SuperHInstrInfo(const SuperHSubtarget &STI);
@@ -59,6 +61,19 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
Register DestReg, Register SrcReg, bool KillSrc,
bool RenamableDest = false,
bool RenamableSrc = false) const override;
+ void storeRegToStackSlot(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
+ bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
+ MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
+ void loadRegFromStackSlot(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg,
+ int FrameIndex, const TargetRegisterClass *RC, Register VReg,
+ unsigned SubReg = 0,
+ MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
+ Register isLoadFromStackSlot(const MachineInstr &MI,
+ int &FrameIndex) const override;
+ Register isStoreToStackSlot(const MachineInstr &MI,
+ int &FrameIndex) const override;
// Branch Analysis
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 98b3fd921a5a4..93d03ebcf3aad 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -50,10 +50,10 @@ def SHSDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
def SHSDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
def SHSDT_PICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
SDTCisPtrTy<1>, SDTCisVT<2, i32>]>;
-def SHSDT_Brcond : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisInt<1>]>;
-def SHSDT_Cmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisInt<2>]>;
-def SHSDT_SelectCC : SDTypeProfile<1, 3,
- [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisInt<3>]>;
+def SHSDT_Brcond : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, OtherVT>]>;
+def SHSDT_Cmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, OtherVT>]>;
+def SHSDT_SelectCC : SDTypeProfile<1, 3,
+ [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>;
//===--------------------------------------------------------------------------===//
// SuperH Specific Nodes
@@ -259,29 +259,29 @@ def MOVRmRn : InstRmRn<0b0110000000000011,
let hasSideEffects = 0 in
def MOVI8Rn : InstRnI8<0b1110000000000000,
(outs GPR:$Rn), (ins imm8:$imm),
- "mov #$imm,$Rn",
- [(set i32:$Rn, imm8:$imm)]>;
+ "mov $imm,$Rn",
+ [(set i32:$Rn, imm:$imm)]>;
// mova @(disp, PC), R0
let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
def MOVAD8PCR0 : InstD8<0b1100011100000000,
- (outs), (ins disp8:$disp),
- "mova @($disp,PC),R0",
- [(set R0, (load disp8:$disp))]>;
+ (outs), (ins pcrel8:$disp),
+ "mova $disp,r0",
+ []>;
// mov.w @(disp,PC), Rn
let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
def MOVWD8PCRn : InstRnD8<0b1001000000000000,
- (outs GPR:$Rn), (ins disp8:$disp),
- "mov.w @($disp,PC),$Rn",
- [(set i32:$Rn, (sextloadi16 disp8:$disp))]>;
+ (outs GPR:$Rn), (ins pcrel8:$disp),
+ "mov.w $disp,$Rn",
+ [(set i32:$Rn, (sextloadi16 constpool:$disp))]>;
// mov.l @(disp,PC), Rn
let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
def MOVLD8PCRn : InstRnD8<0b1101000000000000,
- (outs GPR:$Rn), (ins disp8:$disp),
- "mov.l @($disp,PC),$Rn",
- [(set i32:$Rn, (load disp8:$disp))]>;
+ (outs GPR:$Rn), (ins pcrel8:$disp),
+ "mov.l $disp,$Rn",
+ [(set i32:$Rn, (load constpool:$disp))]>;
// movt Rn
def MOVTRn : InstRn<0b0000000000101001,
@@ -316,38 +316,41 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
// mov.b @Rm, Rn
def MOVBRmiRn : InstRmRn<0b0110000000000000,
- (outs GPR:$Rn), (ins GPR:$Rm),
- "mov.b @$Rm,$Rn",
- [(set i32:$Rn, (sextloadi8 i32:$Rm))]>;
+ (outs GPR:$Rn), (ins IGPR:$Rm),
+ "mov.b $Rm,$Rn",
+ []>;
// mov.w @Rm, Rn
def MOVWRmiRn : InstRmRn<0b0110000000000001,
- (outs GPR:$Rn), (ins GPR:$Rm),
- "mov.w @$Rm,$Rn",
- [(set i32:$Rn, (sextloadi16 i32:$Rm))]>;
+ (outs GPR:$Rn), (ins IGPR:$Rm),
+ "mov.w $Rm,$Rn",
+ []>;
// mov.l @Rm, Rn
def MOVLRmiRn : InstRmRn<0b0110000000000010,
- (outs GPR:$Rn), (ins GPR:$Rm),
- "mov.l @$Rm,$Rn",
- [(set i32:$Rn, (load i32:$Rm))]>;
+ (outs GPR:$Rn), (ins IGPR:$Rm),
+ "mov.l $Rm,$Rn",
+ []>;
// mov.b @Rm+, Rn
+ let isDelayIllegal = 1 in
def MOVBRminciRn : InstRmRn<0b0110000000000100,
- (outs GPR:$Rn), (ins GPR:$Rm),
- "mov.b @$Rm+,$Rn",
+ (outs GPR:$Rn), (ins IGPRInc:$Rm),
+ "mov.b $Rm,$Rn",
[]>;
// mov.w @Rm+, Rn
+ let isDelayIllegal = 1 in
def MOVWRminciRn : InstRmRn<0b0110000000000101,
- (outs GPR:$Rn), (ins GPR:$Rm),
- "mov.w @$Rm+,$Rn",
+ (outs GPR:$Rn), (ins IGPRInc:$Rm),
+ "mov.w $Rm,$Rn",
[]>;
// mov.l @Rm+, Rn
+ let isDelayIllegal = 1 in
def MOVLRminciRn : InstRmRn<0b0110000000000110,
- (outs GPR:$Rn), (ins GPR:$Rm),
- "mov.l @$Rm+,$Rn",
+ (outs GPR:$Rn), (ins IGPRInc:$Rm),
+ "mov.l $Rm,$Rn",
[]>;
// mov.b @(disp, Rm), R0
@@ -366,7 +369,7 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
// mov.l @(disp, Rm), Rn
def MOVLD4RmiRn : InstRmRnD4<0b0101000000000000,
- (outs GPRMem:$Rn), (ins GPR:$Rm, disp4:$disp),
+ (outs GPR:$Rn), (ins GPR:$Rm, disp4:$disp),
"mov.l @($disp,$Rm),$Rn",
[]>;
@@ -424,57 +427,60 @@ let hasSideEffects = 0, mayStore = 1 in {
// mov.b Rm, @Rn
def MOVBRmRni : InstRmRn<0b0010000000000000,
- (outs), (ins GPRMem:$Rn, GPR:$Rm),
- "mov.b $Rm,@$Rn",
- [(truncstorei8 i32:$Rm, GPRMem:$Rn)]>;
+ (outs), (ins GPR:$Rm, IGPR:$Rn),
+ "mov.b $Rm,$Rn",
+ []>;
// mov.w Rm, @Rn
def MOVWRmRni : InstRmRn<0b0010000000000001,
- (outs), (ins GPR:$Rm, GPRMem:$Rn),
- "mov.w $Rm,@$Rn",
- [(truncstorei16 i32:$Rm, GPRMem:$Rn)]>;
+ (outs), (ins GPR:$Rm, IGPR:$Rn),
+ "mov.w $Rm,$Rn",
+ []>;
// mov.l Rm, @Rn
def MOVLRmRni : InstRmRn<0b0010000000000010,
- (outs), (ins GPRMem:$Rn, GPR:$Rm),
- "mov.l $Rm,@$Rn",
- [(store i32:$Rm, GPRMem:$Rn)]>;
+ (outs), (ins GPR:$Rm, IGPR:$Rn),
+ "mov.l $Rm,$Rn",
+ []>;
// mov.b Rm, @-Rn
+ let isDelayIllegal = 1 in
def MOVBRmRndeci : InstRmRn<0b0010000000000100,
- (outs), (ins GPRMem:$Rn, GPR:$Rm),
- "mov.b $Rm, at -$Rn",
+ (outs), (ins GPR:$Rm, IGPRDec:$Rn),
+ "mov.b $Rm,$Rn",
[]>;
// mov.w Rm, @-Rn
+ let isDelayIllegal = 1 in
def MOVWRmRndeci : InstRmRn<0b0010000000000101,
- (outs), (ins GPR:$Rm, GPRMem:$Rn),
- "mov.w $Rm, at -$Rn",
+ (outs), (ins GPR:$Rm, IGPRDec:$Rn),
+ "mov.w $Rm,$Rn",
[]>;
// mov.l Rm, @-Rn
+ let isDelayIllegal = 1 in
def MOVLRmRndeci : InstRmRn<0b0010000000000110,
- (outs), (ins GPRMem:$Rn, GPR:$Rm),
- "mov.l $Rm, at -$Rn",
+ (outs), (ins GPR:$Rm, IGPRDec:$Rn),
+ "mov.l $Rm,$Rn",
[]>;
// mov.b R0, @(disp, Rn)
let Uses = [R0] in
def MOVBR0D4Rni : InstRnD4<0b1000000000000000,
- (outs GPR:$Rn), (ins disp4:$disp),
+ (outs), (ins GPR:$Rn, disp4:$disp),
"mov.b R0,@($disp,$Rn)",
[]>;
// mov.w R0, @(disp, Rn)
let Uses = [R0] in
def MOVWR0D4Rni : InstRnD4<0b1000000100000000,
- (outs GPR:$Rn), (ins disp4:$disp),
+ (outs), (ins GPR:$Rn, disp4:$disp),
"mov.w R0,@($disp,$Rn)",
[]>;
// mov.l Rm, @(disp, Rn)
def MOVLRmD4Rni : InstRmRnD4<0b0001000000000000,
- (outs GPR:$Rn), (ins GPR:$Rm, disp4:$disp),
+ (outs), (ins GPR:$Rn, GPR:$Rm, disp4:$disp),
"mov.l $Rm,@($disp,$Rn)",
[]>;
@@ -547,7 +553,7 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
// add imm:8, Rn
def ADDI8Rn : InstRnI8<0b0111000000000000,
(outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
- "add #$imm,$Rn",
+ "add $imm,$Rn",
[(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
// addc Rm, Rn
@@ -627,20 +633,54 @@ let hasSideEffects = 0 in {
let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+ // mac.w @Rm+, @Rn+
+ let Defs = [MACL] in
+ def MACWRmRn : InstRmRn<0b0100000000001111,
+ (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
+ "mac.w $Rm,$Rn",
+ []>;
+
+ // mac.l @Rm+, @Rn+
+ let Defs = [MACL, MACH] in
+ def MACLRmRn : InstRmRn<0b0000000000001111,
+ (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
+ "mac.l $Rm,$Rn",
+ []>;
+
// mul.l Rm, Rn
let Defs = [MACL] in
- def MULRmRn : InstRmRn<0b0000000000000111,
+ def MULLRmRn : InstRmRn<0b0000000000000111,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"mul.l $Rm,$Rn",
[]>;
- // mulr Rm, Rn
- let Uses = [R0] in
- def MULRR0Rn : InstRn<0b0100000010000000,
- (outs GPR:$Rn), (ins GPR:$src),
- "mulr R0,$Rn",
+ // muls.w Rm, Rn
+ let Defs = [MACL] in
+ def MULSWRmRn : InstRmRn<0b0010000000001111,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "muls.w $Rm,$Rn",
[]>;
+ // mulu.w Rm, Rn
+ let Defs = [MACL] in
+ def MULUWRmRn : InstRmRn<0b0010000000001110,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "mulu.w $Rm,$Rn",
+ []>;
+
+ // dmuls.l Rm, Rn
+ let Defs = [MACL, MACH] in
+ def DMULSLRmRn : InstRmRn<0b0011000000001101,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "dmuls.l $Rm,$Rn",
+ []>;
+
+ // dmulu.l Rm, Rn
+ let Defs = [MACL, MACH] in
+ def DMULULRmRn : InstRmRn<0b0011000000000101,
+ (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ "dmulu.l $Rm,$Rn",
+ []>;
}
@@ -797,7 +837,7 @@ def ANDRmRn : InstRmRn<0b0010000000001001,
let Defs = [R0], Uses = [R0] in
def ANDI8R0 : InstI8<0b1100100100000000,
(outs), (ins imm8:$imm),
- "and #$imm,R0",
+ "and $imm,R0",
[]>;
// not Rm,Rn
@@ -816,7 +856,7 @@ def ORRmRn : InstRmRn<0b0010000000001011,
let Defs = [R0], Uses = [R0] in
def ORI8R0 : InstI8<0b1100101100000000,
(outs), (ins imm8:$imm),
- "or #$imm,R0",
+ "or $imm,R0",
[]>;
// xor Rm,Rn
@@ -829,7 +869,7 @@ def XORRmRn : InstRmRn<0b0010000000001010,
let Defs = [R0], Uses = [R0] in
def XORI8R0 : InstI8<0b1100101000000000,
(outs), (ins imm8:$imm),
- "xor #$imm,R0",
+ "xor $imm,R0",
[]>;
// tst Rm,Rn
@@ -842,7 +882,7 @@ def TSTRmRn : InstRmRn<0b0010000000001000,
let Defs = [SR], Uses = [R0] in
def TSTI8R0 : InstI8<0b1100100000000000,
(outs), (ins imm8:$imm),
- "tst #$imm,R0",
+ "tst $imm,R0",
[]>;
@@ -1010,8 +1050,8 @@ let isTerminator = 1 in {
let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
def JMP : InstRm<0b0100000000101011,
- (outs), (ins GPR:$Rm),
- "jmp @$Rm",
+ (outs), (ins IGPR:$Rm),
+ "jmp $Rm",
[]>;
}
@@ -1024,9 +1064,9 @@ let isTerminator = 1 in {
let isCall = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in {
let Uses = [SR, GBR] in
def JSRRmi : InstRm<0b0100000000001011,
- (outs), (ins GPRMem:$Rm),
- "jsr @$Rm",
- [(SHCall GPRMem:$Rm)]>;
+ (outs), (ins IGPR:$Rm),
+ "jsr $Rm",
+ [(SHCall IGPR:$Rm)]>;
}
@@ -1071,8 +1111,8 @@ def LDCRmSR : InstRm<0b0100000000001110,
// ldc.l @Rm+, SR
let Defs = [SR], isDelayIllegal = 1 in
def LDCLRminciSR : InstRm<0b0100000000000111,
- (outs), (ins GPR:$Rm),
- "ldc.l @$Rm+,SR",
+ (outs), (ins IGPRInc:$Rm),
+ "ldc.l $Rm,SR",
[]>;
// ldc Rm, GBR
@@ -1085,8 +1125,8 @@ def LDCRmGBR : InstRm<0b0100000000011110,
// ldc.l @Rm+, GBR
let Defs = [GBR] in
def LDCLRminciGBR : InstRm<0b0100000000010111,
- (outs), (ins GPR:$Rm),
- "ldc.l @$Rm+,GBR",
+ (outs), (ins IGPRInc:$Rm),
+ "ldc.l $Rm,GBR",
[]>;
// ldc Rm, VBR
@@ -1099,8 +1139,8 @@ def LDCRmVBR : InstRm<0b0100000000101110,
// ldc.l @Rm+, VBR
let Defs = [VBR], isDelayIllegal = 1 in
def LDCLRminciVBR : InstRm<0b0100000000100111,
- (outs), (ins GPR:$Rm),
- "ldc.l @$Rm+,VBR",
+ (outs), (ins IGPRInc:$Rm),
+ "ldc.l $Rm,VBR",
[]>;
// lds Rm, MACH
@@ -1113,8 +1153,8 @@ def LDSRmMACH : InstRm<0b0100000000001010,
// lds.l @Rm+, MACH
let Defs = [MACH] in
def LDSLRminciMACH : InstRm<0b0100000000000110,
- (outs), (ins GPR:$Rm),
- "lds.l @$Rm+,MACH",
+ (outs), (ins IGPRInc:$Rm),
+ "lds.l $Rm,MACH",
[]>;
// lds Rm, MACL
@@ -1127,8 +1167,8 @@ def LDSRmMACL : InstRm<0b0100000000011010,
// lds.l @Rm+, MACL
let Defs = [MACH] in
def LDSLRminciMACL : InstRm<0b0100000000010110,
- (outs), (ins GPR:$Rm),
- "lds.l @$Rm+,MACL",
+ (outs), (ins IGPRInc:$Rm),
+ "lds.l $Rm,MACL",
[]>;
// lds Rm, PR
@@ -1141,8 +1181,8 @@ def LDSRmPR : InstRm<0b0100000000101010,
// lds.l @Rm+, PR
let Defs = [PR] in
def LDSLRminciPR : InstRm<0b0100000000100110,
- (outs), (ins GPR:$Rm),
- "lds.l @$Rm+,PR",
+ (outs), (ins IGPRInc:$Rm),
+ "lds.l $Rm,PR",
[]>;
// nop
@@ -1171,8 +1211,8 @@ def STCSRRn : InstRn<0b0000000000000010,
// stc.l SR, at -Rn
let Uses = [SR], isDelayIllegal = 1 in
def STCLSRRndeci : InstRn<0b0100000000000011,
- (outs GPR:$Rn), (ins),
- "stc.l SR, at -$Rn",
+ (outs IGPRDec:$Rn), (ins),
+ "stc.l SR,$Rn",
[]>;
// stc GBR,Rn
@@ -1185,8 +1225,8 @@ def STCGBRRn : InstRn<0b0000000000010010,
// stc.l GBR, at -Rn
let Uses = [GBR] in
def STCLGBRRndeci : InstRn<0b0100000000010011,
- (outs GPR:$Rn), (ins),
- "stc.l GBR, at -$Rn",
+ (outs IGPRDec:$Rn), (ins),
+ "stc.l GBR,$Rn",
[]>;
// stc VBR,Rn
@@ -1199,8 +1239,8 @@ def STCVBRRn : InstRn<0b0000000000100010,
// stc.l VBR, at -Rn
let Uses = [VBR], isDelayIllegal = 1 in
def STCLVBRRndeci : InstRn<0b0100000000100011,
- (outs GPR:$Rn), (ins),
- "stc.l VBR, at -$Rn",
+ (outs IGPRDec:$Rn), (ins),
+ "stc.l VBR,$Rn",
[]>;
// sts MACH,Rn
@@ -1213,8 +1253,8 @@ def STSMACHRn : InstRn<0b0000000000001010,
// sts.l MACH, at -Rn
let Uses = [MACH] in
def STSLMACHRndeci : InstRn<0b0100000000000010,
- (outs GPR:$Rn), (ins),
- "sts.l MACH, at -$Rn",
+ (outs IGPRDec:$Rn), (ins),
+ "sts.l MACH,$Rn",
[]>;
// sts MACL,Rn
@@ -1227,8 +1267,8 @@ def STSMACLRn : InstRn<0b0000000000011010,
// sts.l MACL, at -Rn
let Uses = [MACL] in
def STSLMACLRndeci : InstRn<0b0100000000010010,
- (outs GPR:$Rn), (ins),
- "sts.l MACL, at -$Rn",
+ (outs IGPRDec:$Rn), (ins),
+ "sts.l MACL,$Rn",
[]>;
// sts PR,Rn
@@ -1241,15 +1281,15 @@ def STSPRRn : InstRn<0b0000000000101010,
// sts.l PR, at -Rn
let Uses = [PR] in
def STSLPRRndeci : InstRn<0b0100000000100010,
- (outs GPR:$Rn), (ins),
- "sts.l PR, at -$Rn",
+ (outs IGPRDec:$Rn), (ins),
+ "sts.l PR,$Rn",
[]>;
// trapa #imm
let Defs = [PC], isCall = 1 in
def TRAPAI8 : InstI8<0b1100001100000000,
(outs), (ins imm8:$imm),
- "trapa #$imm",
+ "trapa $imm",
[]>;
@@ -1277,13 +1317,26 @@ include "SuperHInstrDSP.td"
// Zero-Extend Load
//===--------------------------------------------------------------------------===//
-def : Pat<(i32 (zextloadi1 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
-def : Pat<(i32 (zextloadi8 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
-def : Pat<(i32 (zextloadi16 i32:$src)), (EXTUWRmRn (MOVWRmiRn i32:$src))>;
-def : Pat<(i32 (extloadi1 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
-def : Pat<(i32 (extloadi8 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
-def : Pat<(i32 (extloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
+// def : Pat<(i32 (zextloadi1 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (zextloadi8 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (zextloadi16 i32:$src)), (EXTUWRmRn (MOVWRmiRn i32:$src))>;
+// def : Pat<(i32 (extloadi1 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (extloadi8 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (extloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
+// def : Pat<(i32 (sextloadi1 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (sextloadi8 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (sextloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
+//
+// def : Pat<(sext_inreg i32:$src, i1), (EXTSBRmRn i32:$src)>;
+// def : Pat<(sext_inreg i32:$src, i8), (EXTSBRmRn i32:$src)>;
+// def : Pat<(sext_inreg i32:$src, i16), (EXTSWRmRn i32:$src)>;
+
+//===--------------------------------------------------------------------------===//
+// Truncating Store
+//===--------------------------------------------------------------------------===//
+// def : Pat<(truncstorei8 i32:$src, i32:$dst), (MOVBRmRni i32:$src, i32:$dst)>;
+// def : Pat<(truncstorei16 i32:$src, i32:$dst), (MOVWRmRni i32:$src, i32:$dst)>;
@@ -1293,6 +1346,62 @@ def : Pat<(i32 (extloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+// Loads & Stores
+//===--------------------------------------------------------------------------===//
+
+def LDI8 : SHLoadPseudo<(outs GPR:$dst),
+ (ins IGPR:$src),
+ "; LDI8 PSEUDO",
+ [(set i32:$dst, (sextloadi8 addr:$src))]>;
+
+def LDI16 : SHLoadPseudo<(outs GPR:$dst),
+ (ins IGPR:$src),
+ "; LDI16 PSEUDO",
+ [(set i32:$dst, (sextloadi16 addr:$src))]>;
+
+def LDI32 : SHLoadPseudo<(outs GPR:$dst),
+ (ins IGPR:$src),
+ "; LDI32 PSEUDO",
+ [(set i32:$dst, (load addr:$src))]>;
+
+def STI8 : SHStorePseudo<(outs),
+ (ins GPR:$src, IGPR:$dst),
+ "; STI8 PSEUDO",
+ [(truncstorei8 i32:$src, addr:$dst)]>;
+
+def STI16 : SHStorePseudo<(outs),
+ (ins GPR:$src, IGPR:$dst),
+ "; STI16 PSEUDO",
+ [(truncstorei16 i32:$src, addr:$dst)]>;
+
+def STI32 : SHStorePseudo<(outs),
+ (ins GPR:$src, IGPR:$dst),
+ "; STI32 PSEUDO",
+ [(store i32:$src, addr:$dst)]>;
+
+//===--------------------------------------------------------------------------===//
+// SelectCC & SetCC
+//===--------------------------------------------------------------------------===//
+
+def Select8 : SHSelectPseudo<(outs GPR:$dst),
+ (ins GPR:$src, GPR:$src2, i8imm:$cc),
+ "; Select8 PSEUDO",
+ [(set i8:$dst,
+ (SHselectcc i8:$src, i8:$src2, imm:$cc))]>;
+
+def Select16 : SHSelectPseudo<(outs GPR:$dst),
+ (ins GPR:$src, GPR:$src2, i8imm:$cc),
+ "; Select16 PSEUDO",
+ [(set i16:$dst,
+ (SHselectcc i16:$src, i16:$src2, imm:$cc))]>;
+
+def Select32 : SHSelectPseudo<(outs GPR:$dst),
+ (ins GPR:$src, GPR:$src2, i8imm:$cc),
+ "; Select32 PSEUDO",
+ [(set i32:$dst,
+ (SHselectcc i32:$src, i32:$src2, imm:$cc))]>;
+
//===--------------------------------------------------------------------------===//
// Stack Frame
//===--------------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index d5b7cc883b51f..157e06680e986 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -23,7 +23,7 @@ SuperHMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
const MCExpr *Expr = nullptr;
switch (MO.getTargetFlags()) {
case SHII::MO_NO_FLAG:
- Expr = MCSymbolRefExpr::create(Sym, SH::S_None, Ctx);
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
break;
case SHII::MO_GOT:
@@ -79,11 +79,6 @@ void SuperHMCInstLower::lowerInstruction(const MachineInstr &MI,
MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()), Subtarget);
break;
case MachineOperand::MO_MachineBasicBlock:
-
- // NOTE: Branch instructions will generally jump to labels.
- // so ensure we emit them if they're referenced in an
- // operand during lowering.
- MO.getMBB()->setLabelMustBeEmitted();
MCOp = MCOperand::createExpr(
MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
break;
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
index 880835ebafc49..139e969eb1548 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -47,7 +47,7 @@ SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
}
}
}
-
+
// If not found, create a new one and add it.
MachineFunction &MF = DAG.getMachineFunction();
SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
@@ -120,7 +120,7 @@ SuperHConstantPoolSymbol *SuperHMachineFunctionInfo::tryGetConstant(
unsigned LabelIndex = SFI->createConstIndex();
return SuperHConstantPoolSymbol::Create(
*DAG.getContext(),
- N->getSymbol(),
+ N->getSymbol(),
LabelIndex
);
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 6c40c0f25fdd0..1c7ea011a5ed2 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -60,6 +60,10 @@ SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
return &SH::GPRRegClass;
}
+ if (TRI->isTypeLegalForClass(*RC, MVT::i1)) {
+ return &SH::GPRRegClass;
+ }
+
return TargetRegisterInfo::getLargestLegalSuperClass(RC, MF);
}
@@ -75,6 +79,9 @@ BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
// Also reserve the stack frame and stack pointer.
Reserved.set(SH::R14);
Reserved.set(SH::R15);
+
+ // Status Register
+ Reserved.set(SH::SR);
return Reserved;
}
@@ -88,23 +95,37 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
const MachineFunction &MF = *MBB.getParent();
const MachineFrameInfo &MFI = MF.getFrameInfo();
const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+ const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
const TargetInstrInfo &TII = *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
- // NOTE: Stack grows down, so flip this.
- int Offset = -MFI.getObjectOffset(FrameIndex);
+ int64_t Size = MFI.getObjectSize(FrameIndex);
+ int64_t StackSize = MFI.getStackSize() + 8;
+ int64_t Offset = MFI.getObjectOffset(FrameIndex);
+
+ // Add 4 to offset because SP points to saved FP
+ Offset += StackSize - TFI->getOffsetOfLocalArea() + 4;
- if (MI.getOpcode() == SH::SHFrmIdx) {
+ // Fold incoming offset.
+ Offset += MI.getOperand(FIOperandNum + 1).getImm();
- // TODO: Lower frames that can't be expressed in 4 bits.
+ if (MI.getOpcode() == SH::SHFrmIdx) {
Register DstReg = MI.getOperand(0).getReg();
- MachineInstr *New = BuildMI(MBB, MI, dl, TII.get(SH::MOVLD4RmiRn), DstReg)
- .addReg(SH::R14)
- .addImm(Offset);
+ // mov r14,r1
+ // add #-<frame size>,r1
+ BuildMI(MBB, MI, DebugLoc(), TII.get(SH::MOVRmRn), DstReg)
+ .addReg(SH::R14);
+ BuildMI(MBB, MI, DebugLoc(), TII.get(SH::ADDI8Rn), DstReg)
+ .addReg(DstReg)
+ .addImm(-StackSize);
+
+ II++;
MI.eraseFromParent();
- return false;
}
+
+ MI.getOperand(FIOperandNum).ChangeToRegister(SH::R1, false);
+ MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
return false;
}
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index f826f06f14337..f44b472825f4c 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -18,6 +18,10 @@
//===----------------------------------------------------------------------===//
let Namespace = "SH" in {
+ def sub_8 : SubRegIndex<8>;
+ def sub_16 : SubRegIndex<16>;
+ def sub_32 : SubRegIndex<32>;
+
def sub_64_lo : SubRegIndex<64>;
def sub_64_hi : SubRegIndex<64, 64>;
def sub_32_lo : SubRegIndex<32>;
@@ -43,11 +47,40 @@ class SHReg<bits<16> Enc, string n> : Register<n> {
}
class SHRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs>
- : RegisterWithSubRegs<n, subregs> {
+ : RegisterWithSubRegs<n, subregs> {
let HWEncoding = Enc;
let Namespace = "SH";
}
+// Broken due to issue #218854, resume work on this after it's fixed.
+// // Artificial subregisters of the GPR registers.
+// class GPRReg8<bits<16> Enc, string n>
+// : SHReg<Enc, n # ".b"> {
+// let isArtificial = 1;
+// }
+//
+// class GPRReg16<bits<16> Enc, string n, list<Register> subregs>
+// : SHRegWithSubRegs<Enc, n # ".w", subregs> {
+// let isArtificial = 1;
+// let SubRegIndices = [sub_8];
+// }
+//
+// // SH General Purpose Registers.
+// class GPRReg32<bits<16> Enc, string n, list<Register> subregs>
+// : SHRegWithSubRegs<Enc, n, subregs> {
+// let SubRegIndices = [sub_16];
+// }
+//
+// multiclass GPRReg<bits<16> Enc, string n> {
+// def NAME#B : GPRReg8<Enc, n>;
+// defvar RB = !cast<Register>(NAME#B);
+//
+// def NAME#W : GPRReg16<Enc, n, [RB]>;
+// defvar RW = !cast<Register>(NAME#W);
+//
+// def NAME : GPRReg32<Enc, n, [RW]>;
+// }
+
// SH General Purpose Registers.
class GPRReg<bits<16> Enc, string n> : SHReg<Enc, n>;
@@ -151,7 +184,10 @@ let Namespace = "SH" in {
// Register Classes
//===----------------------------------------------------------------------===//
-def GPR : RegisterClass<"SH", [ i8, i16, i32 ], 32, (sequence "R%u", 0, 15)>;
+def GPR8 : RegisterClass<"SH", [ i8 ], 32, (sequence "R%u", 0, 15)>;
+def GPR16 : RegisterClass<"SH", [ i16 ], 32, (sequence "R%u", 0, 15)>;
+def GPR32 : RegisterClass<"SH", [ i32 ], 32, (sequence "R%u", 0, 15)>;
+def GPR : RegisterClass<"SH", [ i8, i16, i32 ], 32, (sequence "R%u", 0, 15)>;
// 32-bit floating point registers.
def FR32 : RegisterClass<"SH", [ f32 ], 32, (add
>From 0d5402888759cc4b5032bc7f9ed4be2fabe9a764 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 12:59:26 +0200
Subject: [PATCH 34/39] Refactor instruction names
---
.../SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 5 +
.../SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 6 +
.../SuperH/MCTargetDesc/SuperHInstPrinter.h | 1 +
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 39 ++
.../Target/SuperH/SuperHFillDelaySlots.cpp | 2 +-
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 38 +-
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 24 +-
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 113 +++--
llvm/lib/Target/SuperH/SuperHISelLowering.h | 3 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 26 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 422 +++++++++---------
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 4 +-
llvm/lib/Target/SuperH/SuperHRegisterInfo.td | 6 +-
13 files changed, 390 insertions(+), 299 deletions(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 878d658f9e7f3..71bdeb58cb7b3 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -147,6 +147,11 @@ unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixu
default:
return Value;
+ case FK_Data_2:
+ case FK_Data_4:
+ // NOTE: Largest possible displacement is 12 bit, so force this.
+ return (Value & 0xFFF);
+
case SH::fixup_got_low16:
return (Value+Addend) & 65535;
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 22fc26b77b3e7..1a6148b27ca70 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -45,6 +45,12 @@ void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
OS << getRegName(Reg);
}
+void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+ const MCOperand &Op0 = MI->getOperand(OpNo);
+ const MCOperand &Op1 = MI->getOperand(OpNo+1);
+ OS << "@(" << Op1.getImm() << "," << getRegName(Op0.getReg()) << ")";
+}
+
void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
OS << Op.getImm();
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index 17af288324675..328c42c366b24 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -53,6 +53,7 @@ class SuperHInstPrinter : public MCInstPrinter {
void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 8d6c613eef9bf..690515d648564 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -32,6 +32,7 @@
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include <cstdint>
+#include <optional>
using namespace llvm;
@@ -120,6 +121,44 @@ unsigned SuperHMCCodeEmitter::getOpBits(const MCInst &MI,
return getBinaryCodeForInstr(Inst, Fixups, STI);
}
+// @getFixupForOpcode - Helper that gets the neccesary fixup for
+// the given opcode.
+// This is neccesary due to the various opcodes that access memory
+// have different scaling factors applied.
+static std::optional<MCFixup> getFixupForOpcode(unsigned Opcode, const MCExpr *Expr, MCContext &Ctx) {
+ bool isOp32 = isOpcode32(Opcode) ? FK_Data_4 : FK_Data_2;
+
+ switch(Opcode) {
+ default: break;
+
+ // disp * 2
+ case SH::BF:
+ case SH::BFS:
+ case SH::BT:
+ case SH::BTS:
+ case SH::BSR:
+ case SH::BRA:
+ case SH::MOVWI:
+ case SH::MOVWL4:
+ case SH::MOVWLG:
+ case SH::MOVWS4:
+ case SH::MOVWSG:
+ Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(2, Ctx), Ctx);
+ break;
+
+ // disp * 4
+ case SH::MOVA:
+ case SH::MOVLI:
+ case SH::MOVLL4:
+ case SH::MOVLLG:
+ case SH::MOVLS4:
+ case SH::MOVLSG:
+ Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(4, Ctx), Ctx);
+ break;
+ }
+ return MCFixup::create(0, Expr, isOp32 ? FK_Data_4 : FK_Data_2, true);
+}
+
void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 10510a3e13183..d3f950bfb7477 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -85,7 +85,7 @@ MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI)
if (MI.isReturn()) {
// Skip the LDS instruction.
- if (Opcode == SH::LDSLRminciPR || Opcode == SH::LDSRmPR)
+ if (Opcode == SH::LDSPR || Opcode == SH::LDSMPR)
return nullptr;
}
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index e4341a2d59db7..5b3bd8840f0c7 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -67,7 +67,7 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
// Fast path, emit a single immediate add.
// Emit add #-(size),r15
- BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
+ BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI), SP)
.addReg(SP)
.addImm((int)AdjValue);
return true;
@@ -77,7 +77,7 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
// Fast path, emit a single immediate add.
// Emit add #(size),r14
- BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), FP)
+ BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI), FP)
.addReg(FP)
.addImm((int)AdjValue);
return true;
@@ -89,7 +89,7 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
unsigned ToShift = getShiftAmt(AdjValue);
// Empty R0 in case it had something.
- BuildMI(MBB, MBBI, dl, TII.get(SH::MOVI8Rn), SH::R0)
+ BuildMI(MBB, MBBI, dl, TII.get(SH::MOVI), SH::R0)
.addImm(0)
.addReg(SH::R0)
.setMIFlag(MFlag);
@@ -98,10 +98,10 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
// or #(byte), r0
// shll8 r0
for(unsigned i = 0; i < ToShift; i++) {
- BuildMI(MBB, MBBI, dl, TII.get(SH::ORI8R0))
+ BuildMI(MBB, MBBI, dl, TII.get(SH::ORI))
.addImm((AdjValue >> (i*8)) & 0xFF)
.setMIFlag(MFlag);
- BuildMI(MBB, MBBI, dl, TII.get(SH::SHLL8Rn), SH::R0)
+ BuildMI(MBB, MBBI, dl, TII.get(SH::SHLL8), SH::R0)
.addReg(SH::R0)
.setMIFlag(MFlag);
}
@@ -110,12 +110,12 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
// neg r0, r0 (if negative displacement)
// add r0, r15
if (AdjValue < 0)
- BuildMI(MBB, MBBI, dl, TII.get(SH::NEGRmRn), SH::R0)
+ BuildMI(MBB, MBBI, dl, TII.get(SH::NEG), SH::R0)
.addReg(SH::R0)
.addReg(SH::R0)
.setMIFlag(MFlag);
- BuildMI(MBB, MBBI, dl, TII.get(SH::SUBRmRn), SP)
+ BuildMI(MBB, MBBI, dl, TII.get(SH::SUB), SP)
.addReg(SH::R0, RegState::Kill)
.addReg(SP)
.setMIFlag(MFlag);
@@ -149,7 +149,7 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
// Store GOT
if (STI.isPositionIndependent()) {
if (auto *GOTSym = MF.getPICBaseSymbol()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
.addReg(GOT)
.setMIFlag(MachineInstr::FrameSetup);
}
@@ -159,17 +159,17 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
// mov.l r14, at -r15
// add <stackadj>,r15
// mov r15,r14
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
.addReg(FP)
.setMIFlag(MachineInstr::FrameSetup);
emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
.addReg(SP)
.setMIFlag(MachineInstr::FrameSetup);
// Save return address to stack.
if (MFI.hasCalls()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+ BuildMI(MBB, MBBI, DL, TII.get(SH::STSMPR))
.addReg(SP)
.setMIFlag(MachineInstr::FrameSetup);
}
@@ -199,7 +199,7 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
// 1. Restore return address from stack.
if (MFI.hasCalls()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+ BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
.addReg(SP)
.setMIFlag(MachineInstr::FrameDestroy);
}
@@ -207,10 +207,10 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
// 2. Delete stack frame, restoring stack pointer.
if (StackSize > 0) {
emitSPAdj(MF, MBB, MBBI, StackSize);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
.addReg(SP)
.setMIFlag(MachineInstr::FrameDestroy);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRminciRn), SP)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
.addReg(FP)
.setMIFlag(MachineInstr::FrameDestroy);
}
@@ -219,7 +219,7 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
// 1. Restore return address from stack.
if (MFI.hasCalls()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+ BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
.addReg(SP)
.setMIFlag(MachineInstr::FrameDestroy);
}
@@ -230,10 +230,10 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
// mov.l @r15+,r14
if (StackSize > 0) {
emitSPAdj(MF, MBB, MBBI, StackSize);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
.addReg(SP)
.setMIFlag(MachineInstr::FrameDestroy);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRminciRn), SP)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
.addReg(FP)
.setMIFlag(MachineInstr::FrameDestroy);
}
@@ -256,7 +256,7 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
MCRegister Reg = I.getReg();
- BuildMI(MBB, MI, DL, TII.get(SH::MOVLRmRndeci), SP)
+ BuildMI(MBB, MI, DL, TII.get(SH::MOVLM), SP)
.addReg(Reg)
.setMIFlag(MachineInstr::FrameSetup);
}
@@ -283,7 +283,7 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
MCRegister Reg = I.getReg();
- BuildMI(MBB, MI, DL, TII.get(SH::MOVLRminciRn), SP)
+ BuildMI(MBB, MI, DL, TII.get(SH::MOVLM), SP)
.addReg(Reg)
.setMIFlag(MachineInstr::FrameDestroy);
}
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 613e23fccb2d6..ca9b1bebcabb5 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugLog.h"
#define DEBUG_TYPE "sh-isel"
@@ -142,11 +143,12 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
auto DL = CurDAG->getDataLayout();
MVT PtrVT = getTargetLowering()->getPointerTy(DL);
+ LLVM_DEBUG(dbgs() << "SelectAddr\n");
+
// if the address is a frame index get the TargetFrameIndex.
if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
Disp = CurDAG->getTargetConstant(0, dl, MVT::i8);
-
return true;
}
@@ -171,7 +173,7 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
// External Symbols
if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
ReplaceNode(N, Res);
return true;
}
@@ -179,7 +181,7 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
// Global Addresses
if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
ReplaceNode(N, Res);
return true;
}
@@ -187,7 +189,7 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
// Block Addresses
if (auto *CPV = SFI->tryGetConstant((BlockAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
ReplaceNode(N, Res);
return true;
}
@@ -219,31 +221,31 @@ bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
// TST would be faster in this case.
if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
if (C->getSExtValue() == 0) {
- Res = CurDAG->getMachineNode(SH::TSTRmRn, DL, MVT::Glue, LHS, LHS);
+ Res = CurDAG->getMachineNode(SH::TST, DL, MVT::Glue, LHS, LHS);
break;
}
}
- Res = CurDAG->getMachineNode(SH::CMPEQRmRn, DL, MVT::Glue, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPEQ, DL, MVT::Glue, LHS, RHS);
break;
}
case ISD::SETUGE:
case ISD::SETULT: {
- Res = CurDAG->getMachineNode(SH::CMPHSRmRn, DL, MVT::Glue, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPHS, DL, MVT::Glue, LHS, RHS);
break;
}
case ISD::SETOGE:
case ISD::SETOLT: {
- Res = CurDAG->getMachineNode(SH::CMPGERmRn, DL, MVT::Glue, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPGE, DL, MVT::Glue, LHS, RHS);
break;
}
case ISD::SETUGT:
case ISD::SETULE: {
- Res = CurDAG->getMachineNode(SH::CMPGTRmRn, DL, MVT::Glue, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPGT, DL, MVT::Glue, LHS, RHS);
break;
}
case ISD::SETOGT:
case ISD::SETOLE: {
- Res = CurDAG->getMachineNode(SH::CMPHIRmRn, DL, MVT::Glue, LHS, RHS);
+ Res = CurDAG->getMachineNode(SH::CMPHI, DL, MVT::Glue, LHS, RHS);
break;
}
}
@@ -331,7 +333,7 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
SDValue GOT = CurDAG->getTargetExternalSymbol(
"_GLOBAL_OFFSET_TABLE_", MVT::i32, SHII::MO_GOTPC);
MachineSDNode *Res =
- CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, GOT);
+ CurDAG->getMachineNode(SH::MOVA, DL, MVT::i32, GOT);
ReplaceNode(N, Res);
return true;
}
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 299285b73c5c4..78a63370a645e 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -89,6 +89,11 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SREM, VT, Custom);
}
+ // Multiplies have multiple lowerings depending on size.
+ for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
+ setOperationAction(ISD::MUL, VT, Custom);
+ }
+
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
@@ -564,7 +569,7 @@ SDValue SuperHTargetLowering::LowerCallResult(
// DIVISION LOWERING
//===----------------------------------------------------------------------===//
-SDValue SuperHTargetLowering::LowerDiv(SDValue Op, SelectionDAG &DAG) const {
+SDValue SuperHTargetLowering::LowerDIV(SDValue Op, SelectionDAG &DAG) const {
unsigned Opcode = Op->getOpcode();
assert((Opcode == ISD::SDIV || Opcode == ISD::UDIV) &&
"Invalid opcode for Div lowering");
@@ -625,6 +630,66 @@ SDValue SuperHTargetLowering::LowerDiv(SDValue Op, SelectionDAG &DAG) const {
+//===----------------------------------------------------------------------===//
+// MULTIPLICATION LOWERING
+//===----------------------------------------------------------------------===//
+SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
+ unsigned Opcode = Op->getOpcode();
+ assert((Opcode == ISD::MUL) && "Invalid opcode for MUL lowering");
+ SDLoc DL(Op);
+
+ EVT VT = Op->getValueType(0);
+ Type *Ty = VT.getTypeForEVT(*DAG.getContext());
+
+ switch (VT.getSimpleVT().SimpleTy) {
+ default:
+ llvm_unreachable("Unexpected type for ");
+ case MVT::i8: {
+ SDValue MulOp = DAG.getNode(SH::MULS, DL, MVT::i32, Op.getValue(0), Op.getValue(1));
+ return DAG.getNode(SH::LDSMACL, DL, MVT::i32, MulOp);
+ }
+ case MVT::i16: {
+ SDValue MulOp = DAG.getNode(SH::MULS, DL, MVT::i32, Op.getValue(0), Op.getValue(1));
+ return DAG.getNode(SH::LDSMACL, DL, MVT::i32, MulOp);
+ }
+
+ case MVT::i32: {
+ // 32-bit multiplication requires lowering to __mulsi3
+ SDValue InChain = DAG.getEntryNode();
+
+ TargetLowering::ArgListTy Args;
+ for (SDValue const &Value : Op->op_values()) {
+ TargetLowering::ArgListEntry Entry(
+ Value, Value.getValueType().getTypeForEVT(*DAG.getContext()));
+ Args.push_back(Entry);
+ }
+
+ RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(RTLIB::MUL_I32);
+ if (LCImpl == RTLIB::Unsupported)
+ return SDValue();
+
+ SDValue Callee =
+ DAG.getExternalSymbol(LCImpl, getPointerTy(DAG.getDataLayout()));
+
+ Type *RetTy = (Type *)StructType::get(Ty, Ty);
+
+
+ TargetLowering::CallLoweringInfo CLI(DAG);
+ CLI.setDebugLoc(DL)
+ .setChain(InChain)
+ .setLibCallee(DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy,
+ Callee, std::move(Args))
+ .setInRegister();
+
+ std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
+ return CallInfo.first;
+ }
+ }
+}
+
+
+
+
//===----------------------------------------------------------------------===//
// CUSTOM LOWERING
//===----------------------------------------------------------------------===//
@@ -633,7 +698,9 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
switch(Op->getOpcode()) {
case ISD::UDIV:
case ISD::SDIV:
- return LowerDiv(Op, DAG);
+ return LowerDIV(Op, DAG);
+ case ISD::MUL:
+ return LowerMUL(Op, DAG);
case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG);
case ISD::ExternalSymbol:
@@ -656,38 +723,6 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-// Load/Store Lowering
-//===----------------------------------------------------------------------===//
-
-MachineBasicBlock *SuperHTargetLowering::insertLoad(MachineInstr &MI,
- MachineBasicBlock *MBB) const {
- DEBUG_FN_PRINT()
- MachineFunction &MF = *MBB->getParent();
- const MachineFrameInfo &MFI = MF.getFrameInfo();
- const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
- const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
-
- MachineOperand Dest = MI.getOperand(0);
- MachineOperand Offset = MI.getOperand(1);
-
- // Target index load.
- if (Dest.isTargetIndex()) {
-
- }
-
- MI.eraseFromParent();
- return MBB;
-}
-
-MachineBasicBlock *SuperHTargetLowering::insertStore(MachineInstr &MI,
- MachineBasicBlock *MBB) const {
- DEBUG_FN_PRINT()
-
- MI.eraseFromParent();
- return MBB;
-}
-
@@ -712,7 +747,7 @@ MachineBasicBlock *SuperHTargetLowering::insertSELECTCC(MachineInstr &MI,
// Lower True-False selection
if (TrueV.isImm() && FalseV.isImm()) {
if (TrueV.getImm() == 1 && FalseV.getImm() == 0) {
- BuildMI(*MBB, BBI, DL, TII.get(SH::MOVTRn), SH::R0);
+ BuildMI(*MBB, BBI, DL, TII.get(SH::MOVT), SH::R0);
MI.eraseFromParent();
return MBB;
}
@@ -797,14 +832,6 @@ SuperHTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
case SH::Select16:
case SH::Select32:
return insertSELECTCC(MI, MBB);
- case SH::LDI8:
- case SH::LDI16:
- case SH::LDI32:
- return insertLoad(MI, MBB);
- case SH::STI8:
- case SH::STI16:
- case SH::STI32:
- return insertStore(MI, MBB);
}
return MBB;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 6f761b167f98e..a7b29f3640372 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -65,7 +65,8 @@ class SuperHTargetLowering : public TargetLowering {
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerDiv(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerDIV(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 2b24bd6372234..e65d05a4c2276 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -133,7 +133,7 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
// If the targets are GPR registers, use MOV Rm, Rn.
if (SH::GPRRegClass.contains(DestReg, SrcReg)) {
- BuildMI(MBB, MI, DL, get(SH::MOVRmRn), DestReg)
+ BuildMI(MBB, MI, DL, get(SH::MOV), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
return;
};
@@ -162,13 +162,13 @@ void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBl
Register SrcStrReg;
unsigned Opcode = 0;
if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
- Opcode = SH::MOVBR0D4Rni;
+ Opcode = SH::MOVBS4;
SrcStrReg = SH::R0;
} else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
- Opcode = SH::MOVWR0D4Rni;
+ Opcode = SH::MOVWS4;
SrcStrReg = SH::R0;
} else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
- Opcode = SH::MOVLRmD4Rni;
+ Opcode = SH::MOVLS4;
SrcStrReg = SrcReg;
} else {
llvm_unreachable("Cannot store this register into a stack slot!");
@@ -176,16 +176,16 @@ void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBl
// mov r14,r1
// add #-<frame size>,r1
- BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SH::R1)
+ BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SH::R1)
.addReg(SH::R14);
- BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI8Rn), SH::R1)
+ BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI), SH::R1)
.addReg(SH::R1)
.addImm(-(int)MFI.getStackSize());
// mov srcreg,r0
// mov.b/w r0,@(<offset>,r1)
if (SrcStrReg != SrcReg) {
- BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SrcStrReg)
+ BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SrcStrReg)
.addReg(SrcReg, getKillRegState(isKill));
BuildMI(MBB, MI, DebugLoc(), get(Opcode))
.addReg(SH::R1)
@@ -221,13 +221,13 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
unsigned Opcode = 0;
Register DstStrReg;
if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
- Opcode = SH::MOVBD4RmiR0;
+ Opcode = SH::MOVBL4;
DstStrReg = SH::R0;
} else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
- Opcode = SH::MOVWD4RmiR0;
+ Opcode = SH::MOVWL4;
DstStrReg = SH::R0;
} else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
- Opcode = SH::MOVLD4RmiRn;
+ Opcode = SH::MOVLL4;
DstStrReg = DestReg;
} else {
llvm_unreachable("Cannot load this register into a stack slot!");
@@ -235,9 +235,9 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
// mov r14,r1
// add #-<frame size>,r1
- BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SH::R1)
+ BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SH::R1)
.addReg(SH::R14);
- BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI8Rn), SH::R1)
+ BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI), SH::R1)
.addReg(SH::R1)
.addImm(-(int)MFI.getStackSize());
@@ -247,7 +247,7 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
BuildMI(MBB, MI, DebugLoc(), get(Opcode))
.addReg(SH::R1)
.addImm(Offset);
- BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), DestReg)
+ BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), DestReg)
.addReg(DstStrReg);
return;
}
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 93d03ebcf3aad..7e1c22e132a61 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -197,7 +197,15 @@ def IGPR : SHIndirectRegOp<GPR, "">;
def IGPRInc : SHIndirectRegOp<GPR, "Inc">;
def IGPRDec : SHIndirectRegOp<GPR, "Dec">;
-// Addressing mode pattern reg+imm6
+// Register Indirect with Displacement @(disp,Rm)
+def memri : Operand<iPTR> {
+ let MIOperandInfo = (ops GPR, disp8);
+ let OperandType = "OPERAND_MEMORY";
+ let EncoderMethod = "getMemriOpValue";
+ let PrintMethod = "printMemri";
+}
+
+// Addressing mode pattern reg+disp
let WantsRoot = true in
def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
@@ -237,9 +245,7 @@ def HasSH4 : Predicate<"Subtarget->hasSH4Inst()">,
AssemblerPredicate<(all_of FeatureSH4)>;
def HasSH4A : Predicate<"Subtarget->hasSH4AInst()">,
- AssemblerPredicate<(all_of FeatureSH4A)>;
-
-
+ AssemblerPredicate<(all_of FeatureSH4A)>;
//===--------------------------------------------------------------------------===//
@@ -247,62 +253,66 @@ def HasSH4A : Predicate<"Subtarget->hasSH4AInst()">,
// Data Transfer Instructions
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
+// NOTE: The names of the instructions are taken from the SH manual's
+// Pseudocode examples for each instruction.
+// When adding new instructions, please keep this naming scheme.
+//===--------------------------------------------------------------------------===//
// mov Rm, Rn
let hasSideEffects = 0 in
-def MOVRmRn : InstRmRn<0b0110000000000011,
+def MOV : InstRmRn<0b0110000000000011,
(outs GPR:$Rn), (ins GPR:$Rm),
"mov $Rm,$Rn",
[]>;
// mov #imm:8, Rn
let hasSideEffects = 0 in
-def MOVI8Rn : InstRnI8<0b1110000000000000,
+def MOVI : InstRnI8<0b1110000000000000,
(outs GPR:$Rn), (ins imm8:$imm),
"mov $imm,$Rn",
[(set i32:$Rn, imm:$imm)]>;
// mova @(disp, PC), R0
let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
-def MOVAD8PCR0 : InstD8<0b1100011100000000,
+def MOVA : InstD8<0b1100011100000000,
(outs), (ins pcrel8:$disp),
"mova $disp,r0",
[]>;
// mov.w @(disp,PC), Rn
let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
-def MOVWD8PCRn : InstRnD8<0b1001000000000000,
+def MOVWI : InstRnD8<0b1001000000000000,
(outs GPR:$Rn), (ins pcrel8:$disp),
"mov.w $disp,$Rn",
[(set i32:$Rn, (sextloadi16 constpool:$disp))]>;
// mov.l @(disp,PC), Rn
let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
-def MOVLD8PCRn : InstRnD8<0b1101000000000000,
+def MOVLI : InstRnD8<0b1101000000000000,
(outs GPR:$Rn), (ins pcrel8:$disp),
"mov.l $disp,$Rn",
[(set i32:$Rn, (load constpool:$disp))]>;
// movt Rn
-def MOVTRn : InstRn<0b0000000000101001,
+def MOVT : InstRn<0b0000000000101001,
(outs GPR:$Rn), (ins),
"movt $Rn",
[]>;
// swap.b Rm,Rn
-def SWAPBRmRn : InstRmRn<0b0110000000001000,
+def SWAPB : InstRmRn<0b0110000000001000,
(outs GPR:$Rn), (ins GPR:$Rm),
"swap.b $Rm,$Rn",
[]>;
// swap.w Rm,Rn
-def SWAPWRmRn : InstRmRn<0b0110000000001001,
+def SWAPW : InstRmRn<0b0110000000001001,
(outs GPR:$Rn), (ins GPR:$Rm),
"swap.w $Rm,$Rn",
[]>;
// xtrct Rm,Rn
-def XTRCTRmRn : InstRmRn<0b0010000000001101,
+def XTRCT : InstRmRn<0b0010000000001101,
(outs GPR:$Rn), (ins GPR:$Rm),
"xtrct $Rm,$Rn",
[]>;
@@ -315,102 +325,102 @@ def XTRCTRmRn : InstRmRn<0b0010000000001101,
let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
// mov.b @Rm, Rn
- def MOVBRmiRn : InstRmRn<0b0110000000000000,
+ def MOVBL : InstRmRn<0b0110000000000000,
(outs GPR:$Rn), (ins IGPR:$Rm),
"mov.b $Rm,$Rn",
- []>;
+ [(set i32:$Rn, (sextloadi8 IGPR:$Rm))]>;
// mov.w @Rm, Rn
- def MOVWRmiRn : InstRmRn<0b0110000000000001,
+ def MOVWL : InstRmRn<0b0110000000000001,
(outs GPR:$Rn), (ins IGPR:$Rm),
"mov.w $Rm,$Rn",
- []>;
+ [(set i32:$Rn, (sextloadi16 IGPR:$Rm))]>;
// mov.l @Rm, Rn
- def MOVLRmiRn : InstRmRn<0b0110000000000010,
+ def MOVLL : InstRmRn<0b0110000000000010,
(outs GPR:$Rn), (ins IGPR:$Rm),
"mov.l $Rm,$Rn",
- []>;
+ [(set i32:$Rn, (load IGPR:$Rm))]>;
// mov.b @Rm+, Rn
let isDelayIllegal = 1 in
- def MOVBRminciRn : InstRmRn<0b0110000000000100,
+ def MOVBP : InstRmRn<0b0110000000000100,
(outs GPR:$Rn), (ins IGPRInc:$Rm),
"mov.b $Rm,$Rn",
[]>;
// mov.w @Rm+, Rn
let isDelayIllegal = 1 in
- def MOVWRminciRn : InstRmRn<0b0110000000000101,
+ def MOVWP : InstRmRn<0b0110000000000101,
(outs GPR:$Rn), (ins IGPRInc:$Rm),
"mov.w $Rm,$Rn",
[]>;
// mov.l @Rm+, Rn
let isDelayIllegal = 1 in
- def MOVLRminciRn : InstRmRn<0b0110000000000110,
+ def MOVLP : InstRmRn<0b0110000000000110,
(outs GPR:$Rn), (ins IGPRInc:$Rm),
"mov.l $Rm,$Rn",
[]>;
// mov.b @(disp, Rm), R0
let Defs = [R0] in
- def MOVBD4RmiR0 : InstRmD4<0b1000010000000000,
- (outs), (ins GPR:$Rm, disp4:$disp),
- "mov.b @($disp,$Rm),R0",
- []>;
+ def MOVBL4 : InstRmD4<0b1000010000000000,
+ (outs), (ins (memri $Rm, $disp):$src),
+ "mov.b $src,R0",
+ [(set R0, (sextloadi8 addr:$src))]>;
// mov.w @(disp, Rm), R0
let Defs = [R0] in
- def MOVWD4RmiR0 : InstRmD4<0b1000010100000000,
- (outs), (ins GPR:$Rm, disp4:$disp),
- "mov.w @($disp,$Rm),R0",
- []>;
+ def MOVWL4 : InstRmD4<0b1000010100000000,
+ (outs), (ins (memri $Rm, $disp):$src),
+ "mov.w $src,R0",
+ [(set R0, (sextloadi16 addr:$src))]>;
// mov.l @(disp, Rm), Rn
- def MOVLD4RmiRn : InstRmRnD4<0b0101000000000000,
- (outs GPR:$Rn), (ins GPR:$Rm, disp4:$disp),
- "mov.l @($disp,$Rm),$Rn",
- []>;
+ def MOVLL4 : InstRmRnD4<0b0101000000000000,
+ (outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+ "mov.l $src,$Rn",
+ [(set i32:$Rn, (load addr:$src))]>;
// mov.b @(R0,Rm),Rn
let Uses = [R0] in
- def MOVBR0RmiRn : InstRmRn<0b0000000000001100,
+ def MOVBL0 : InstRmRn<0b0000000000001100,
(outs GPR:$Rn), (ins GPR:$Rm),
"mov.b @(R0,Rm),Rn",
[]>;
// mov.w @(R0,Rm),Rn
let Uses = [R0] in
- def MOVWR0RmiRn : InstRmRn<0b0000000000001101,
+ def MOVWL0 : InstRmRn<0b0000000000001101,
(outs GPR:$Rn), (ins GPR:$Rm),
"mov.w @(R0,$Rm),$Rn",
[]>;
// mov.l @(R0,Rm),Rn
let Uses = [R0] in
- def MOVLR0RmiRn : InstRmRn<0b0000000000001110,
+ def MOVLL0 : InstRmRn<0b0000000000001110,
(outs GPR:$Rn), (ins GPR:$Rm),
"mov.l @(R0,$Rm),$Rn",
[]>;
// mov.b @(disp,GBR),R0
let Defs = [R0], Uses = [GBR] in
- def MOVBD12GBRiR0 : InstD8<0b1100010000000000,
+ def MOVBLG : InstD8<0b1100010000000000,
(outs), (ins disp12:$disp),
"mov.b @($disp,GBR),R0",
[]>;
// mov.w @(disp,GBR),R0
let Defs = [R0], Uses = [GBR] in
- def MOVWD12GBRiR0 : InstD8<0b1100010100000000,
+ def MOVWLG : InstD8<0b1100010100000000,
(outs), (ins disp12:$disp),
"mov.w @($disp,GBR),R0",
[]>;
// mov.l @(disp,GBR),R0
let Defs = [R0], Uses = [GBR] in
- def MOVLD12GBRiR0 : InstD8<0b1100011000000000,
+ def MOVLLG : InstD8<0b1100011000000000,
(outs), (ins disp12:$disp),
"mov.l @($disp,GBR),R0",
[]>;
@@ -426,102 +436,102 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
let hasSideEffects = 0, mayStore = 1 in {
// mov.b Rm, @Rn
- def MOVBRmRni : InstRmRn<0b0010000000000000,
+ def MOVBS : InstRmRn<0b0010000000000000,
(outs), (ins GPR:$Rm, IGPR:$Rn),
"mov.b $Rm,$Rn",
- []>;
+ [(truncstorei8 i32:$Rm, i32:$Rn)]>;
// mov.w Rm, @Rn
- def MOVWRmRni : InstRmRn<0b0010000000000001,
+ def MOVWS : InstRmRn<0b0010000000000001,
(outs), (ins GPR:$Rm, IGPR:$Rn),
"mov.w $Rm,$Rn",
- []>;
+ [(truncstorei16 i32:$Rm, i32:$Rn)]>;
// mov.l Rm, @Rn
- def MOVLRmRni : InstRmRn<0b0010000000000010,
+ def MOVLS : InstRmRn<0b0010000000000010,
(outs), (ins GPR:$Rm, IGPR:$Rn),
"mov.l $Rm,$Rn",
- []>;
+ [/*(store i32:$Rm, i32:$Rn)*/]>;
// mov.b Rm, @-Rn
let isDelayIllegal = 1 in
- def MOVBRmRndeci : InstRmRn<0b0010000000000100,
+ def MOVBM : InstRmRn<0b0010000000000100,
(outs), (ins GPR:$Rm, IGPRDec:$Rn),
"mov.b $Rm,$Rn",
[]>;
// mov.w Rm, @-Rn
let isDelayIllegal = 1 in
- def MOVWRmRndeci : InstRmRn<0b0010000000000101,
+ def MOVWM : InstRmRn<0b0010000000000101,
(outs), (ins GPR:$Rm, IGPRDec:$Rn),
"mov.w $Rm,$Rn",
[]>;
// mov.l Rm, @-Rn
let isDelayIllegal = 1 in
- def MOVLRmRndeci : InstRmRn<0b0010000000000110,
+ def MOVLM : InstRmRn<0b0010000000000110,
(outs), (ins GPR:$Rm, IGPRDec:$Rn),
"mov.l $Rm,$Rn",
[]>;
// mov.b R0, @(disp, Rn)
let Uses = [R0] in
- def MOVBR0D4Rni : InstRnD4<0b1000000000000000,
- (outs), (ins GPR:$Rn, disp4:$disp),
- "mov.b R0,@($disp,$Rn)",
- []>;
+ def MOVBS4 : InstRnD4<0b1000000000000000,
+ (outs), (ins (memri $Rn, $disp):$dst),
+ "mov.b r0,$dst",
+ [/*(truncstorei8 i32, addr:$dst)*/]>;
// mov.w R0, @(disp, Rn)
let Uses = [R0] in
- def MOVWR0D4Rni : InstRnD4<0b1000000100000000,
- (outs), (ins GPR:$Rn, disp4:$disp),
- "mov.w R0,@($disp,$Rn)",
- []>;
+ def MOVWS4 : InstRnD4<0b1000000100000000,
+ (outs), (ins (memri $Rn, $disp):$dst),
+ "mov.w r0,$dst",
+ [/*(truncstorei16 i32, addr:$dst)*/]>;
// mov.l Rm, @(disp, Rn)
- def MOVLRmD4Rni : InstRmRnD4<0b0001000000000000,
- (outs), (ins GPR:$Rn, GPR:$Rm, disp4:$disp),
- "mov.l $Rm,@($disp,$Rn)",
- []>;
+ def MOVLS4 : InstRmRnD4<0b0001000000000000,
+ (outs), (ins GPR:$Rm, (memri $Rn, $disp):$dst),
+ "mov.l $Rm,$dst",
+ [(store i32:$Rm, addr:$dst)]>;
// mov.b Rm,@(R0,Rn)
let Uses = [R0] in
- def MOVBRmR0Rni : InstRmRn<0b0000000000000100,
+ def MOVBS0 : InstRmRn<0b0000000000000100,
(outs), (ins GPR:$Rm, GPR:$Rn),
"mov.b $Rm,@(R0,$Rn)",
[]>;
// mov.w Rm,@(R0,Rn)
let Uses = [R0] in
- def MOVWRmR0Rni : InstRmRn<0b0000000000000101,
+ def MOVWS0 : InstRmRn<0b0000000000000101,
(outs), (ins GPR:$Rm, GPR:$Rn),
"mov.w $Rm,@(R0,$Rn)",
[]>;
// mov.l Rm,@(R0,Rn)
let Uses = [R0] in
- def MOVLRmR0Rni : InstRmRn<0b0000000000000110,
+ def MOVLS0 : InstRmRn<0b0000000000000110,
(outs), (ins GPR:$Rm, GPR:$Rn),
"mov.l $Rm,@(R0,$Rn)",
[]>;
// mov.b R0,@(disp,GBR)
let Uses = [R0, GBR] in
- def MOVBR0D12GBRi : InstD8<0b1100000000000000,
+ def MOVBSG : InstD8<0b1100000000000000,
(outs), (ins disp12:$disp),
"mov.b R0,@($disp,GBR)",
[]>;
// mov.w R0,@(disp,GBR)
let Uses = [R0, GBR] in
- def MOVWR0D12GBRi : InstD8<0b1100000100000000,
+ def MOVWSG : InstD8<0b1100000100000000,
(outs), (ins disp12:$disp),
"mov.w R0,@($disp,GBR)",
[]>;
// mov.l R0,@(disp,GBR)
let Uses = [R0, GBR] in
- def MOVLR0D12GBRi : InstD8<0b1100001000000000,
+ def MOVLSG : InstD8<0b1100001000000000,
(outs), (ins disp12:$disp),
"mov.l R0,@($disp,GBR)",
[]>;
@@ -545,27 +555,27 @@ let hasSideEffects = 0, mayStore = 1 in {
let hasSideEffects = 0, Constraints = "$src = $Rn" in {
// add Rm, Rn
- def ADDRmRn : InstRmRn<0b0011000000001100,
+ def ADD : InstRmRn<0b0011000000001100,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"add $Rm,$Rn",
[(set i32:$Rn, (add i32:$Rm, i32:$src))]>;
// add imm:8, Rn
- def ADDI8Rn : InstRnI8<0b0111000000000000,
+ def ADDI : InstRnI8<0b0111000000000000,
(outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
"add $imm,$Rn",
[(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
// addc Rm, Rn
let Defs = [SR], Uses = [SR], isCommutable = 1 in
- def ADDCRmRn : InstRmRn<0b0011000000001110,
+ def ADDC : InstRmRn<0b0011000000001110,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"addc $Rm,$Rn",
[(set i32:$Rn, (adde i32:$Rm, i32:$src))]>;
// addv Rm, Rn
let Defs = [SR], isCommutable = 1 in
- def ADDVRmRn : InstRmRn<0b0011000000001111,
+ def ADDV : InstRmRn<0b0011000000001111,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"addv $Rm,$Rn",
[(set i32:$Rn, (addc i32:$Rm, i32:$src))]>;
@@ -581,28 +591,28 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// sub Rm, Rn
- def SUBRmRn : InstRmRn<0b0011000000001000,
+ def SUB : InstRmRn<0b0011000000001000,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"sub $Rm,$Rn",
[(set i32:$Rn, (sub i32:$Rm, i32:$src))]>;
// subc Rm, Rn
let Defs = [SR], Uses = [SR] in
- def SUBCRmRn : InstRmRn<0b0011000000001010,
+ def SUBC : InstRmRn<0b0011000000001010,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"subc $Rm,$Rn",
[(set i32:$Rn, (sube i32:$Rm, i32:$src))]>;
// subv Rm, Rn
let Defs = [SR] in
- def SUBVRmRn : InstRmRn<0b0011000000001011,
+ def SUBV : InstRmRn<0b0011000000001011,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"subv $Rm,$Rn",
[(set i32:$Rn, (subc i32:$Rm, i32:$src))]>;
// dt Rn
let Defs = [SR] in
- def DTRn : InstRn<0b0100000000010000,
+ def DT : InstRn<0b0100000000010000,
(outs GPR:$Rn), (ins GPR:$src),
"dt $Rn",
[(set i32:$Rn, (sub i32:$src, -1))]>;
@@ -611,14 +621,14 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
let hasSideEffects = 0 in {
// neg Rm, Rn
- def NEGRmRn : InstRmRn<0b0110000000001011,
+ def NEG : InstRmRn<0b0110000000001011,
(outs GPR:$Rn), (ins GPR:$Rm),
"neg $Rm,$Rn",
[(set i32:$Rn, (ineg i32:$Rm))]>;
// negc Rm, Rn
let Defs = [SR], Uses = [SR] in
- def NEGCRmRn : InstRmRn<0b0110000000001010,
+ def NEGC : InstRmRn<0b0110000000001010,
(outs GPR:$Rn), (ins GPR:$Rm),
"negc $Rm,$Rn",
[(set i32:$Rn, (ineg i32:$Rm))]>;
@@ -634,50 +644,50 @@ let hasSideEffects = 0 in {
let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
// mac.w @Rm+, @Rn+
- let Defs = [MACL] in
- def MACWRmRn : InstRmRn<0b0100000000001111,
+ let Defs = [MACLO] in
+ def MACW : InstRmRn<0b0100000000001111,
(outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
"mac.w $Rm,$Rn",
[]>;
// mac.l @Rm+, @Rn+
- let Defs = [MACL, MACH] in
- def MACLRmRn : InstRmRn<0b0000000000001111,
+ let Defs = [MACLO, MACHI] in
+ def MACL : InstRmRn<0b0000000000001111,
(outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
"mac.l $Rm,$Rn",
[]>;
// mul.l Rm, Rn
- let Defs = [MACL] in
- def MULLRmRn : InstRmRn<0b0000000000000111,
+ let Defs = [MACLO] in
+ def MULL : InstRmRn<0b0000000000000111,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"mul.l $Rm,$Rn",
[]>;
// muls.w Rm, Rn
- let Defs = [MACL] in
- def MULSWRmRn : InstRmRn<0b0010000000001111,
+ let Defs = [MACLO] in
+ def MULS : InstRmRn<0b0010000000001111,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"muls.w $Rm,$Rn",
[]>;
// mulu.w Rm, Rn
- let Defs = [MACL] in
- def MULUWRmRn : InstRmRn<0b0010000000001110,
+ let Defs = [MACLO] in
+ def MULU : InstRmRn<0b0010000000001110,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"mulu.w $Rm,$Rn",
[]>;
// dmuls.l Rm, Rn
- let Defs = [MACL, MACH] in
- def DMULSLRmRn : InstRmRn<0b0011000000001101,
+ let Defs = [MACLO, MACHI] in
+ def DMULS : InstRmRn<0b0011000000001101,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"dmuls.l $Rm,$Rn",
[]>;
// dmulu.l Rm, Rn
- let Defs = [MACL, MACH] in
- def DMULULRmRn : InstRmRn<0b0011000000000101,
+ let Defs = [MACLO, MACHI] in
+ def DMULU : InstRmRn<0b0011000000000101,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"dmulu.l $Rm,$Rn",
[]>;
@@ -694,7 +704,7 @@ let hasSideEffects = 0, isCommutable = 1 in {
// div0s Rm, Rn
let Defs = [SR] in
- def DIV0SRmRn : InstRmRn<0b0010000000000111,
+ def DIV0S : InstRmRn<0b0010000000000111,
(outs), (ins GPR:$Rm, GPR:$Rn),
"div0s $Rm,$Rn",
[]>;
@@ -708,7 +718,7 @@ let hasSideEffects = 0, isCommutable = 1 in {
// div1 Rm, Rn
let Defs = [SR] in
- def DIV1RmRn : InstRmRn<0b0011000000000100,
+ def DIV1 : InstRmRn<0b0011000000000100,
(outs GPR:$Rn), (ins GPR:$Rm),
"div1 $Rm,$Rn",
[]>;
@@ -722,27 +732,27 @@ let hasSideEffects = 0, isCommutable = 1 in {
//===--------------------------------------------------------------------------===//
// exts.b Rm, Rn
-def EXTSBRmRn : InstRmRn<0b0110000000001110,
+def EXTSB : InstRmRn<0b0110000000001110,
(outs GPR:$Rn), (ins GPR:$Rm),
"exts.b $Rm,$Rn",
[(set i32:$Rn, (sext i8:$Rm))]>;
// exts.w Rm, Rn
-def EXTSWRmRn : InstRmRn<0b0110000000001111,
+def EXTSW : InstRmRn<0b0110000000001111,
(outs GPR:$Rn), (ins GPR:$Rm),
"exts.w $Rm,$Rn",
- [(set i32:$Rn, (sext i16:$Rm))]>;
+ [(set i32:$Rn, (sext i16:$Rm))]>;
// extu.b Rm, Rn
-def EXTUBRmRn : InstRmRn<0b0110000000001100,
- (outs GPR:$Rn), (ins GPR:$Rm),
- "extu.b $Rm,$Rn",
- [(set i32:$Rn, (zext i8:$Rm))]>;
+def EXTUB : InstRmRn<0b0110000000001100,
+ (outs GPR:$Rn), (ins GPR:$Rm),
+ "extu.b $Rm,$Rn",
+ [(set i32:$Rn, (zext i8:$Rm))]>;
// extu.w Rm, Rn
-def EXTUWRmRn : InstRmRn<0b0110000000001101,
+def EXTUW : InstRmRn<0b0110000000001101,
(outs GPR:$Rn), (ins GPR:$Rm),
- "extu.w $Rm,$Rn",
+ "extu.w $Rm,$Rn",
[(set i32:$Rn, (zext i16:$Rm))]>;
@@ -755,63 +765,63 @@ def EXTUWRmRn : InstRmRn<0b0110000000001101,
// cmp/eq #imm,R0
let Defs = [R0, SR] in
-def CMPEQI8R0 : InstI8<0b1000100000000000,
+def CMPIM : InstI8<0b1000100000000000,
(outs), (ins imm8:$imm),
"cmp/eq #imm,R0",
[]>;
// cmp/eq Rm,Rn
let Defs = [SR] in
-def CMPEQRmRn : InstRmRn<0b0011000000000000,
+def CMPEQ : InstRmRn<0b0011000000000000,
(outs), (ins GPR:$Rm, GPR:$Rn),
"cmp/eq $Rm,$Rn",
[]>;
// cmp/hs Rm,Rn
let Defs = [SR] in
-def CMPHSRmRn : InstRmRn<0b0011000000000010,
+def CMPHS : InstRmRn<0b0011000000000010,
(outs), (ins GPR:$Rm, GPR:$Rn),
"cmp/hs $Rm,$Rn",
[]>;
// cmp/ge Rm,Rn
let Defs = [SR] in
-def CMPGERmRn : InstRmRn<0b0011000000000011,
+def CMPGE : InstRmRn<0b0011000000000011,
(outs), (ins GPR:$Rm, GPR:$Rn),
"cmp/ge $Rm,$Rn",
[]>;
// cmp/hi Rm,Rn
let Defs = [SR] in
-def CMPHIRmRn : InstRmRn<0b0011000000000110,
+def CMPHI : InstRmRn<0b0011000000000110,
(outs), (ins GPR:$Rm, GPR:$Rn),
"cmp/hi $Rm,$Rn",
[]>;
// cmp/gt Rm,Rn
let Defs = [SR] in
-def CMPGTRmRn : InstRmRn<0b0011000000000111,
+def CMPGT : InstRmRn<0b0011000000000111,
(outs), (ins GPR:$Rm, GPR:$Rn),
"cmp/gt $Rm,$Rn",
[]>;
// cmp/pl Rn
let Defs = [SR] in
-def CMPPLRn : InstRn<0b0100000000010101,
+def CMPPL : InstRn<0b0100000000010101,
(outs), (ins GPR:$Rn),
"cmp/pl $Rn",
[]>;
// cmp/pz Rn
let Defs = [SR] in
-def CMPPZRn : InstRn<0b0100000000010001,
+def CMPPZ : InstRn<0b0100000000010001,
(outs), (ins GPR:$Rn),
"cmp/pz $Rn",
[]>;
// cmp/str Rm,Rn
let Defs = [SR] in
-def CMPSTRRmRn : InstRmRn<0b0010000000001100,
+def CMPSTR : InstRmRn<0b0010000000001100,
(outs), (ins GPR:$Rm, GPR:$Rn),
"cmp/str $Rm,$Rn",
[]>;
@@ -829,60 +839,94 @@ def CMPSTRRmRn : InstRmRn<0b0010000000001100,
// and Rm,Rn
let Constraints = "$src = $Rn" in
-def ANDRmRn : InstRmRn<0b0010000000001001,
+def AND : InstRmRn<0b0010000000001001,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"and $Rm,$Rn",
[(set i32:$Rn, (and i32:$Rm, i32:$src))]>;
// and #imm,R0
let Defs = [R0], Uses = [R0] in
-def ANDI8R0 : InstI8<0b1100100100000000,
+def ANDI : InstI8<0b1100100100000000,
(outs), (ins imm8:$imm),
"and $imm,R0",
[]>;
+// and #imm,@(R0,GBR)
+let Uses = [R0, GBR] in
+def ANDM : InstI8<0b1100110100000000,
+ (outs), (ins imm8:$imm),
+ "and $imm,@(r0,gbr)",
+ []>;
// not Rm,Rn
-def NOTRmRn : InstRmRn<0b0110000000000111,
+def NOT : InstRmRn<0b0110000000000111,
(outs GPR:$Rn), (ins GPR:$Rm),
"not $Rm,$Rn",
[(set i32:$Rn, (not i32:$Rm))]>;
// or Rm,Rn
let Constraints = "$src = $Rn" in
-def ORRmRn : InstRmRn<0b0010000000001011,
+def OR : InstRmRn<0b0010000000001011,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"or $Rm,$Rn",
[(set i32:$Rn, (or i32:$Rm, i32:$src))]>;
// or #imm,R0
let Defs = [R0], Uses = [R0] in
-def ORI8R0 : InstI8<0b1100101100000000,
+def ORI : InstI8<0b1100101100000000,
(outs), (ins imm8:$imm),
"or $imm,R0",
[]>;
+// or.b #imm,@(R0,GBR)
+let Uses = [R0, GBR] in
+def ORM : InstI8<0b1100111100000000,
+ (outs), (ins imm8:$imm),
+ "or.b $imm,@(r0,gbr)",
+ []>;
// xor Rm,Rn
let Constraints = "$src = $Rn" in
-def XORRmRn : InstRmRn<0b0010000000001010,
+def XOR : InstRmRn<0b0010000000001010,
(outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
"xor $Rm,$Rn",
[(set i32:$Rn, (xor i32:$Rm, i32:$src))]>;
+
// xor #imm,R0
let Defs = [R0], Uses = [R0] in
-def XORI8R0 : InstI8<0b1100101000000000,
+def XORI : InstI8<0b1100101000000000,
+ (outs), (ins imm8:$imm),
+ "xor $imm,r0",
+ []>;
+
+// xor.b #imm,@(R0,GBR)
+let Defs = [R0], Uses = [R0] in
+def XORM : InstI8<0b1100111000000000,
(outs), (ins imm8:$imm),
- "xor $imm,R0",
+ "xor.b $imm,@(r0,gbr)",
+ []>;
+
+// tas.b @Rn
+let Defs = [SR] in
+def TAS : InstRn<0b0010000000001000,
+ (outs), (ins IGPR:$Rn),
+ "tas.b $Rn",
[]>;
// tst Rm,Rn
let Defs = [SR] in
-def TSTRmRn : InstRmRn<0b0010000000001000,
+def TST : InstRmRn<0b0010000000001000,
(outs), (ins GPR:$Rm, GPR:$Rn),
"tst $Rm,$Rn",
[]>;
// tst #imm,R0
let Defs = [SR], Uses = [R0] in
-def TSTI8R0 : InstI8<0b1100100000000000,
+def TSTI : InstI8<0b1100100000000000,
+ (outs), (ins imm8:$imm),
+ "tst $imm,r0",
+ []>;
+
+// tst.b #imm,@(R0,GBR)
+let Defs = [SR], Uses = [R0, GBR] in
+def TSTM : InstI8<0b1100110000000000,
(outs), (ins imm8:$imm),
- "tst $imm,R0",
+ "tst.b $imm,@(r0,gbr)",
[]>;
@@ -899,93 +943,93 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
// rotcl Rn
let Defs = [SR] in
- def ROTCLRn : InstRn<0b0100000000100100,
+ def ROTCL : InstRn<0b0100000000100100,
(outs GPR:$Rn), (ins GPR:$src),
"rotcl $Rn",
[]>;
// rotcr Rn
let Defs = [SR] in
- def ROTCRRn : InstRn<0b0100000000100101,
+ def ROTCR : InstRn<0b0100000000100101,
(outs GPR:$Rn), (ins GPR:$src),
"rotcr $Rn",
[]>;
// rotl Rn
let Defs = [SR] in
- def ROTLRn : InstRn<0b0100000000000100,
+ def ROTL : InstRn<0b0100000000000100,
(outs GPR:$Rn), (ins GPR:$src),
"rotl $Rn",
[(set i32:$Rn, (rotl i32:$src, (i8 1)))]>;
// rotr Rn
let Defs = [SR] in
- def ROTRRn : InstRn<0b0100000000000101,
+ def ROTR : InstRn<0b0100000000000101,
(outs GPR:$Rn), (ins GPR:$src),
"rotr $Rn",
[(set i32:$Rn, (rotr i32:$src, (i8 1)))]>;
// shal Rn
let Defs = [SR] in
- def SHALRn : InstRn<0b0100000000100000,
+ def SHAL : InstRn<0b0100000000100000,
(outs GPR:$Rn), (ins GPR:$src),
"shal $Rn",
[]>;
// shar Rn
let Defs = [SR] in
- def SHARRn : InstRn<0b0100000000100001,
+ def SHAR : InstRn<0b0100000000100001,
(outs GPR:$Rn), (ins GPR:$src),
"shar $Rn",
[(set i32:$Rn, (sra i32:$src, (i8 1)))]>;
// shll Rn
let Defs = [SR] in
- def SHLLRn : InstRn<0b0100000000000000,
+ def SHLL : InstRn<0b0100000000000000,
(outs GPR:$Rn), (ins GPR:$src),
"shll $Rn",
[(set i32:$Rn, (shl i32:$src, (i8 1)))]>;
// shll2 Rn
let Defs = [SR] in
- def SHLL2Rn : InstRn<0b0100000000001000,
+ def SHLL2 : InstRn<0b0100000000001000,
(outs GPR:$Rn), (ins GPR:$src),
"shll2 $Rn",
[(set i32:$Rn, (shl i32:$src, (i8 2)))]>;
// shll8 Rn
- def SHLL8Rn : InstRn<0b0100000000011000,
+ def SHLL8 : InstRn<0b0100000000011000,
(outs GPR:$Rn), (ins GPR:$src),
"shll8 $Rn",
[(set i32:$Rn, (shl i32:$src, (i8 8)))]>;
// shll16 Rn
- def SHLL16Rn : InstRn<0b0100000000101000,
+ def SHLL16 : InstRn<0b0100000000101000,
(outs GPR:$Rn), (ins GPR:$src),
"shll16 $Rn",
[(set i32:$Rn, (shl i32:$src, (i8 16)))]>;
// shlr Rn
let Defs = [SR] in
- def SHLRRn : InstRn<0b0100000000000001,
+ def SHLR : InstRn<0b0100000000000001,
(outs GPR:$Rn), (ins GPR:$src),
"shlr $Rn",
[(set i32:$Rn, (srl i32:$src, (i8 1)))]>;
// shlr2 Rn
- def SHLR2Rn : InstRn<0b0100000000001001,
+ def SHLR2 : InstRn<0b0100000000001001,
(outs GPR:$Rn), (ins GPR:$src),
"shlr2 $Rn",
[(set i32:$Rn, (srl i32:$src, (i8 2)))]>;
// shlr8 Rn
- def SHLR8Rn : InstRn<0b0100000000011001,
+ def SHLR8 : InstRn<0b0100000000011001,
(outs GPR:$Rn), (ins GPR:$src),
"shlr8 $Rn",
[(set i32:$Rn, (srl i32:$src, (i8 8)))]>;
// shlr16 Rn
- def SHLR16Rn : InstRn<0b0100000000101001,
+ def SHLR16 : InstRn<0b0100000000101001,
(outs GPR:$Rn), (ins GPR:$src),
"shlr16 $Rn",
[(set i32:$Rn, (srl i32:$src, (i8 16)))]>;
@@ -1062,8 +1106,8 @@ let isTerminator = 1 in {
//===--------------------------------------------------------------------------===//
let isCall = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in {
- let Uses = [SR, GBR] in
- def JSRRmi : InstRm<0b0100000000001011,
+ let Uses = [PR, PC] in
+ def JSR : InstRm<0b0100000000001011,
(outs), (ins IGPR:$Rm),
"jsr $Rm",
[(SHCall IGPR:$Rm)]>;
@@ -1103,84 +1147,84 @@ def CLRT : Inst<0b0000000000001000, (outs), (ins), "clrt", []>;
// ldc Rm, SR
let Defs = [SR], isDelayIllegal = 1 in
-def LDCRmSR : InstRm<0b0100000000001110,
+def LDCSR : InstRm<0b0100000000001110,
(outs), (ins GPR:$Rm),
"ldc $Rm,SR",
[]>;
// ldc.l @Rm+, SR
let Defs = [SR], isDelayIllegal = 1 in
-def LDCLRminciSR : InstRm<0b0100000000000111,
+def LDCMSR : InstRm<0b0100000000000111,
(outs), (ins IGPRInc:$Rm),
"ldc.l $Rm,SR",
[]>;
// ldc Rm, GBR
let Defs = [GBR] in
-def LDCRmGBR : InstRm<0b0100000000011110,
+def LDCGBR : InstRm<0b0100000000011110,
(outs), (ins GPR:$Rm),
"ldc $Rm,GBR",
[]>;
// ldc.l @Rm+, GBR
let Defs = [GBR] in
-def LDCLRminciGBR : InstRm<0b0100000000010111,
+def LDCMGBR : InstRm<0b0100000000010111,
(outs), (ins IGPRInc:$Rm),
"ldc.l $Rm,GBR",
[]>;
// ldc Rm, VBR
let Defs = [VBR], isDelayIllegal = 1 in
-def LDCRmVBR : InstRm<0b0100000000101110,
+def LDCVBR : InstRm<0b0100000000101110,
(outs), (ins GPR:$Rm),
"ldc $Rm,VBR",
[]>;
// ldc.l @Rm+, VBR
let Defs = [VBR], isDelayIllegal = 1 in
-def LDCLRminciVBR : InstRm<0b0100000000100111,
+def LDCMVBR : InstRm<0b0100000000100111,
(outs), (ins IGPRInc:$Rm),
"ldc.l $Rm,VBR",
[]>;
// lds Rm, MACH
-let Defs = [MACH] in
-def LDSRmMACH : InstRm<0b0100000000001010,
+let Defs = [MACHI] in
+def LDSMACH : InstRm<0b0100000000001010,
(outs), (ins GPR:$Rm),
"lds $Rm,MACH",
[]>;
// lds.l @Rm+, MACH
-let Defs = [MACH] in
-def LDSLRminciMACH : InstRm<0b0100000000000110,
+let Defs = [MACHI] in
+def LDSMMACH : InstRm<0b0100000000000110,
(outs), (ins IGPRInc:$Rm),
"lds.l $Rm,MACH",
[]>;
// lds Rm, MACL
-let Defs = [MACH] in
-def LDSRmMACL : InstRm<0b0100000000011010,
+let Defs = [MACLO] in
+def LDSMACL : InstRm<0b0100000000011010,
(outs), (ins GPR:$Rm),
"lds $Rm,MACL",
[]>;
// lds.l @Rm+, MACL
-let Defs = [MACH] in
-def LDSLRminciMACL : InstRm<0b0100000000010110,
+let Defs = [MACLO] in
+def LDSMMACL : InstRm<0b0100000000010110,
(outs), (ins IGPRInc:$Rm),
"lds.l $Rm,MACL",
[]>;
// lds Rm, PR
let Defs = [PR] in
-def LDSRmPR : InstRm<0b0100000000101010,
+def LDSPR : InstRm<0b0100000000101010,
(outs), (ins GPR:$Rm),
"lds $Rm,PR",
[]>;
// lds.l @Rm+, PR
let Defs = [PR] in
-def LDSLRminciPR : InstRm<0b0100000000100110,
+def LDSMPR : InstRm<0b0100000000100110,
(outs), (ins IGPRInc:$Rm),
"lds.l $Rm,PR",
[]>;
@@ -1203,91 +1247,91 @@ def SLEEP : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
// stc SR,Rn
let Uses = [SR], isDelayIllegal = 1 in
-def STCSRRn : InstRn<0b0000000000000010,
+def STCSR : InstRn<0b0000000000000010,
(outs GPR:$Rn), (ins),
"stc SR,$Rn",
[]>;
// stc.l SR, at -Rn
let Uses = [SR], isDelayIllegal = 1 in
-def STCLSRRndeci : InstRn<0b0100000000000011,
+def STCMSR : InstRn<0b0100000000000011,
(outs IGPRDec:$Rn), (ins),
"stc.l SR,$Rn",
[]>;
// stc GBR,Rn
let Uses = [GBR] in
-def STCGBRRn : InstRn<0b0000000000010010,
+def STCGBR : InstRn<0b0000000000010010,
(outs GPR:$Rn), (ins),
"stc GBR,$Rn",
[]>;
// stc.l GBR, at -Rn
let Uses = [GBR] in
-def STCLGBRRndeci : InstRn<0b0100000000010011,
+def STCMGBR : InstRn<0b0100000000010011,
(outs IGPRDec:$Rn), (ins),
"stc.l GBR,$Rn",
[]>;
// stc VBR,Rn
let Uses = [VBR], isDelayIllegal = 1 in
-def STCVBRRn : InstRn<0b0000000000100010,
+def STCVBR : InstRn<0b0000000000100010,
(outs GPR:$Rn), (ins),
"stc VBR,$Rn",
[]>;
// stc.l VBR, at -Rn
let Uses = [VBR], isDelayIllegal = 1 in
-def STCLVBRRndeci : InstRn<0b0100000000100011,
+def STCMVBR : InstRn<0b0100000000100011,
(outs IGPRDec:$Rn), (ins),
"stc.l VBR,$Rn",
[]>;
// sts MACH,Rn
-let Uses = [MACH] in
-def STSMACHRn : InstRn<0b0000000000001010,
+let Uses = [MACHI] in
+def STSMACH : InstRn<0b0000000000001010,
(outs GPR:$Rn), (ins),
"sts MACH,$Rn",
[]>;
// sts.l MACH, at -Rn
-let Uses = [MACH] in
-def STSLMACHRndeci : InstRn<0b0100000000000010,
+let Uses = [MACHI] in
+def STSMMACH : InstRn<0b0100000000000010,
(outs IGPRDec:$Rn), (ins),
"sts.l MACH,$Rn",
[]>;
// sts MACL,Rn
-let Uses = [MACL] in
-def STSMACLRn : InstRn<0b0000000000011010,
+let Uses = [MACLO] in
+def STSMACL : InstRn<0b0000000000011010,
(outs GPR:$Rn), (ins),
"sts MACL,$Rn",
[]>;
// sts.l MACL, at -Rn
-let Uses = [MACL] in
-def STSLMACLRndeci : InstRn<0b0100000000010010,
+let Uses = [MACLO] in
+def STSMMACL : InstRn<0b0100000000010010,
(outs IGPRDec:$Rn), (ins),
"sts.l MACL,$Rn",
[]>;
// sts PR,Rn
let Uses = [PR] in
-def STSPRRn : InstRn<0b0000000000101010,
+def STSPR : InstRn<0b0000000000101010,
(outs GPR:$Rn), (ins),
"sts PR,$Rn",
[]>;
// sts.l PR, at -Rn
let Uses = [PR] in
-def STSLPRRndeci : InstRn<0b0100000000100010,
+def STSMPR : InstRn<0b0100000000100010,
(outs IGPRDec:$Rn), (ins),
"sts.l PR,$Rn",
[]>;
// trapa #imm
let Defs = [PC], isCall = 1 in
-def TRAPAI8 : InstI8<0b1100001100000000,
+def TRAPA : InstI8<0b1100001100000000,
(outs), (ins imm8:$imm),
"trapa $imm",
[]>;
@@ -1326,7 +1370,7 @@ include "SuperHInstrDSP.td"
// def : Pat<(i32 (sextloadi1 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
// def : Pat<(i32 (sextloadi8 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
// def : Pat<(i32 (sextloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
-//
+
// def : Pat<(sext_inreg i32:$src, i1), (EXTSBRmRn i32:$src)>;
// def : Pat<(sext_inreg i32:$src, i8), (EXTSBRmRn i32:$src)>;
// def : Pat<(sext_inreg i32:$src, i16), (EXTSWRmRn i32:$src)>;
@@ -1346,40 +1390,6 @@ include "SuperHInstrDSP.td"
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
-//===--------------------------------------------------------------------------===//
-// Loads & Stores
-//===--------------------------------------------------------------------------===//
-
-def LDI8 : SHLoadPseudo<(outs GPR:$dst),
- (ins IGPR:$src),
- "; LDI8 PSEUDO",
- [(set i32:$dst, (sextloadi8 addr:$src))]>;
-
-def LDI16 : SHLoadPseudo<(outs GPR:$dst),
- (ins IGPR:$src),
- "; LDI16 PSEUDO",
- [(set i32:$dst, (sextloadi16 addr:$src))]>;
-
-def LDI32 : SHLoadPseudo<(outs GPR:$dst),
- (ins IGPR:$src),
- "; LDI32 PSEUDO",
- [(set i32:$dst, (load addr:$src))]>;
-
-def STI8 : SHStorePseudo<(outs),
- (ins GPR:$src, IGPR:$dst),
- "; STI8 PSEUDO",
- [(truncstorei8 i32:$src, addr:$dst)]>;
-
-def STI16 : SHStorePseudo<(outs),
- (ins GPR:$src, IGPR:$dst),
- "; STI16 PSEUDO",
- [(truncstorei16 i32:$src, addr:$dst)]>;
-
-def STI32 : SHStorePseudo<(outs),
- (ins GPR:$src, IGPR:$dst),
- "; STI32 PSEUDO",
- [(store i32:$src, addr:$dst)]>;
-
//===--------------------------------------------------------------------------===//
// SelectCC & SetCC
//===--------------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 1c7ea011a5ed2..b861431ca934d 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -114,9 +114,9 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
// mov r14,r1
// add #-<frame size>,r1
- BuildMI(MBB, MI, DebugLoc(), TII.get(SH::MOVRmRn), DstReg)
+ BuildMI(MBB, MI, DebugLoc(), TII.get(SH::MOV), DstReg)
.addReg(SH::R14);
- BuildMI(MBB, MI, DebugLoc(), TII.get(SH::ADDI8Rn), DstReg)
+ BuildMI(MBB, MI, DebugLoc(), TII.get(SH::ADDI), DstReg)
.addReg(DstReg)
.addImm(-StackSize);
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index f44b472825f4c..f63c9e09670d5 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -146,8 +146,8 @@ let Namespace = "SH" in {
// System Registers
def PC : SysReg<0, "pc">, DwarfRegNum<[16]>; // Program Counter
def PR : SysReg<0, "pr">, DwarfRegNum<[17]>; // Procedure Register
- def MACH : SysReg<1, "mach">, DwarfRegNum<[20]>; // Mult & Accum Hi
- def MACL : SysReg<0, "macl">, DwarfRegNum<[21]>; // Mult & Accum Low
+ def MACHI : SysReg<1, "mach">, DwarfRegNum<[20]>; // Mult & Accum Hi
+ def MACLO : SysReg<0, "macl">, DwarfRegNum<[21]>; // Mult & Accum Low
def FPUL : SysReg<0, "fpul">, DwarfRegNum<[23]>; // FPU Comms Register
def FPSCR : SysReg<0, "fpscr">, DwarfRegNum<[24]>; // FPU Status/Control Register
@@ -221,7 +221,7 @@ def CTRL : RegisterClass<"SH", [ i32 ], 32,
// System registers.
def SYS : RegisterClass<"SH", [ i32 ], 32,
- (add PR, PC, MACL, MACH, FPSCR, FPUL)>, Unallocatable;
+ (add PR, PC, MACLO, MACHI, FPSCR, FPUL)>, Unallocatable;
// Program Counter
def R_PC : RegisterClass<"SH", [ i32 ], 32, (add PC)>, Unallocatable;
>From d4c6932fff9636fd4f6a1291c65b6b5961c2edeb Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 4 Sep 2026 04:32:55 +0200
Subject: [PATCH 35/39] Refactor fixups
---
.../SuperH/MCTargetDesc/SuperHAsmBackend.cpp | 129 ++++++----------
.../MCTargetDesc/SuperHELFObjectWriter.cpp | 131 +++-------------
.../SuperH/MCTargetDesc/SuperHFixupKinds.h | 145 ++----------------
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 64 +++++---
llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp | 14 +-
.../Target/SuperH/SuperHConstantPoolValue.cpp | 2 +-
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 44 +++---
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 8 +-
llvm/lib/Target/SuperH/SuperHMCInstLower.cpp | 36 ++---
9 files changed, 181 insertions(+), 392 deletions(-)
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 71bdeb58cb7b3..5adcf90b23458 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -77,45 +77,13 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
// SuperHFixupKinds.h.
//
// Name offset bits flags
- {"fixup_got32", 0, 32, 0},
- {"fixup_got_low16", 10, 16, 0},
- {"fixup_got_medlow16", 10, 16, 0},
- {"fixup_got_medhi16", 10, 16, 0},
- {"fixup_got_hi16", 10, 16, 0},
- {"fixup_got10by4", 10, 10, 0},
- {"fixup_got10by8", 10, 10, 0},
- {"fixup_plt32", 0, 32, 0},
- {"fixup_plt_low16", 10, 16, 0},
- {"fixup_plt_medlow16", 10, 16, 0},
- {"fixup_plt_medhi16", 10, 16, 0},
- {"fixup_plt_hi16", 10, 16, 0},
- {"fixup_gotplt32", 0, 32, 0},
- {"fixup_gotplt_low16", 10, 16, 0},
- {"fixup_gotplt_medlow16", 10, 16, 0},
- {"fixup_gotplt_medhi16", 10, 16, 0},
- {"fixup_gotplt_hi16", 10, 16, 0},
- {"fixup_gotoff", 0, 32, 0},
- {"fixup_gotoff_low16", 10, 16, 0},
- {"fixup_gotoff_medlow16", 10, 16, 0},
- {"fixup_gotoff_medhi16", 10, 16, 0},
- {"fixup_gotoff_hi16", 10, 16, 0},
- {"fixup_gotpc", 0, 32, 0},
- {"fixup_gotpc_low16" , 10, 16, 0},
- {"fixup_gotpc_medlow16" , 10, 16, 0},
- {"fixup_gotpc_medhi16" , 10, 16, 0},
- {"fixup_gotpc_hi16" , 10, 16, 0},
- {"fixup_copy", 0, 0, 0},
- {"fixup_copy64", 0, 0, 0},
- {"fixup_glob_dat", 0, 32, 0},
- {"fixup_glob_dat64", 0, 64, 0},
- {"fixup_jump_slot", 0, 32, 0},
- {"fixup_jump_slot64", 0, 64, 0},
- {"fixup_relative", 0, 32, 0},
- {"fixup_relative64", 0, 64, 0},
- {"fixup_dir32", 0, 32, 0},
- {"fixup_rel32", 0, 32, 0},
- {"fixup_64", 0, 64, 0},
- {"fixup_64_pcrel", 0, 64, 0},
+ {"fixup_32", 0, 32, 0},
+ {"fixup_pcrel4_by2", 0, 16, 0},
+ {"fixup_pcrel4_by4", 0, 16, 0},
+ {"fixup_pcrel8_by4", 0, 16, 0},
+ {"fixup_pcrel8_4by2", 0, 16, 0},
+ {"fixup_pcrel8_4by4", 0, 16, 0},
+ {"fixup_pcrel12_4by2", 0, 16, 0},
};
// clang-format on
@@ -131,11 +99,6 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
return Infos[Kind - FirstTargetFixupKind];
}
-std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup &Fixup,
- MCValue &Target, uint64_t &FixedValue) {
- return {};
-}
-
unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target, uint64_t Value,
bool IsResolved, MCContext &Ctx,
@@ -147,55 +110,58 @@ unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixu
default:
return Value;
- case FK_Data_2:
- case FK_Data_4:
- // NOTE: Largest possible displacement is 12 bit, so force this.
- return (Value & 0xFFF);
-
- case SH::fixup_got_low16:
- return (Value+Addend) & 65535;
-
- case SH::fixup_got_medlow16:
- return ((Value+Addend) >> 16) & 65535;
+ case SH::fixup_32:
+ return (Value+Addend) & 0xFFFFFFFF;
- case SH::fixup_got_medhi16:
- return ((Value+Addend) >> 32) & 65535;
+ case SH::fixup_pcrel4_by2:
+ return ((Value+Addend) / 2) & 0xF;
- case SH::fixup_got_hi16:
- return ((Value+Addend) >> 48) & 65535;
-
- case SH::fixup_got10by4:
- return (Value+Addend) / 4;
-
- case SH::fixup_got10by8:
- return (Value+Addend) / 8;
-
- case SH::fixup_relative:
- case SH::fixup_relative64:
- return Value+Addend;
-
- case SH::fixup_dir32:
- return (Value+Addend);
-
- case SH::fixup_rel32:
- return Value+Addend;
+ case SH::fixup_pcrel4_by4:
+ return ((Value+Addend) / 4) & 0xF;
+
+ case SH::fixup_pcrel8_by4:
+ return ((Value+Addend) / 4) & 0xFF;
+
+ case SH::fixup_pcrel8_4by2:
+ return ((alignTo(Value, 2) + Addend - 4) / 2) & 0xFF;
+
+ case SH::fixup_pcrel8_4by4:
+ return ((alignTo(Value, 4) + Addend - 4) / 4) & 0xFF;
+
+ case SH::fixup_pcrel12_4by2:
+ return ((alignTo(Value, 2) + Addend - 4) / 2) & 0xFFF;
}
}
bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target, uint64_t &FixedValue,
bool IsResolved) {
+ if (!IsResolved) {
+ Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
+ return false;
+ }
+ return true;
+}
+
+std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup &Fixup,
+ MCValue &Target, uint64_t &FixedValue) {
MCValue PCITarget; // PC-Indirect Target
// Get indirect target location.
switch(Fixup.getKind()) {
default:
- return false;
+ return {};
case FK_Data_1:
case FK_Data_2:
case FK_Data_4:
- case FK_Data_8: {
+ case FK_Data_8:
+ case SH::fixup_pcrel4_by2:
+ case SH::fixup_pcrel4_by4:
+ case SH::fixup_pcrel8_by4:
+ case SH::fixup_pcrel8_4by2:
+ case SH::fixup_pcrel8_4by4:
+ case SH::fixup_pcrel12_4by2: {
const auto *EValue = Fixup.getValue();
if (!EValue->evaluateAsRelocatable(PCITarget, Asm))
return true;
@@ -213,20 +179,17 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
return false;
// Check if resolvable.
- IsResolved = &SA.getSection() == F.getParent() &&
- SA.getBinding() == ELF::STB_LOCAL &&
- SA.getType() != ELF::STT_GNU_IFUNC;
- if (!IsResolved) {
- Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
+ bool IsResolved = &SA.getSection() == F.getParent() &&
+ SA.getBinding() == ELF::STB_LOCAL &&
+ SA.getType() != ELF::STT_GNU_IFUNC;
+ if (!IsResolved)
return false;
- }
// Calculate fixed offset value.
// Note that the PC relative jumps are based on the start of the address.
// So it must be subtracted from the fixed value.
FixedValue = Asm->getSymbolOffset(SA) + PCITarget.getConstant();
FixedValue -= (Asm->getFragmentOffset(F) + Fixup.getOffset());
- FixedValue /= 4; // Values are aligned to 4 bytes.
return true;
}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index 292d55241e814..b7910e8bb2315 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -51,8 +51,8 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
case FK_Data_1:
case FK_Data_2:
case FK_Data_8:
- return 0;
-
+ return ELF::R_SH_NONE;
+
case FK_Data_4: {
switch (Spec) {
case SH::S_None:
@@ -60,121 +60,28 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
case SH::S_PCREL:
return ELF::R_SH_REL32;
default:
- return SH::S_DIR;
+ return ELF::R_SH_NONE;
+ }
+ }
+
+ case SH::fixup_pcrel4_by2:
+ case SH::fixup_pcrel4_by4:
+ case SH::fixup_pcrel8_by4:
+ case SH::fixup_pcrel8_4by2:
+ case SH::fixup_pcrel12_4by2: {
+ switch (Spec) {
+ case SH::S_None:
+ return ELF::R_SH_DIR32;
+ case SH::S_PCREL:
+ return ELF::R_SH_REL32;
+ default:
+ return ELF::R_SH_NONE;
}
}
- case SH::fixup_got32:
- return ELF::R_SH_GOT32;
-
- case SH::fixup_got_low16:
- return ELF::R_SH_GOT_LOW16;
-
- case SH::fixup_got_medlow16:
- return ELF::R_SH_GOT_MEDLOW16;
-
- case SH::fixup_got_medhi16:
- return ELF::R_SH_GOT_MEDHI16;;
-
- case SH::fixup_got_hi16:
- return ELF::R_SH_GOT_HI16;
-
- case SH::fixup_plt32:
- return ELF::R_SH_PLT32;
-
- case SH::fixup_plt_low16:
- return ELF::R_SH_PLT_LOW16;
-
- case SH::fixup_plt_medlow16:
- return ELF::R_SH_PLT_MEDLOW16;
-
- case SH::fixup_plt_medhi16:
- return ELF::R_SH_PLT_MEDHI16;;
-
- case SH::fixup_plt_hi16:
- return ELF::R_SH_PLT_HI16;
-
- case SH::fixup_gotplt32:
- return ELF::R_SH_GOTPLT32;
-
- case SH::fixup_gotplt_low16:
- return ELF::R_SH_GOTPLT_LOW16;
-
- case SH::fixup_gotplt_medlow16:
- return ELF::R_SH_GOTPLT_MEDLOW16;
-
- case SH::fixup_gotplt_medhi16:
- return ELF::R_SH_GOTPLT_MEDHI16;;
-
- case SH::fixup_gotplt_hi16:
- return ELF::R_SH_GOTPLT_HI16;
-
- case SH::fixup_gotoff:
- return ELF::R_SH_GOTOFF;
-
- case SH::fixup_gotoff_low16:
- return ELF::R_SH_GOTOFF_LOW16;
-
- case SH::fixup_gotoff_medlow16:
- return ELF::R_SH_GOTOFF_MEDLOW16;
-
- case SH::fixup_gotoff_medhi16:
- return ELF::R_SH_GOTOFF_MEDHI16;;
-
- case SH::fixup_gotoff_hi16:
- return ELF::R_SH_GOTOFF_HI16;
-
- case SH::fixup_gotpc:
- return ELF::R_SH_GOTPC;
-
- case SH::fixup_gotpc_low16:
- return ELF::R_SH_GOTPC_LOW16;
-
- case SH::fixup_gotpc_medlow16:
- return ELF::R_SH_GOTPC_MEDLOW16;
-
- case SH::fixup_gotpc_medhi16:
- return ELF::R_SH_GOTPC_MEDHI16;;
-
- case SH::fixup_gotpc_hi16:
- return ELF::R_SH_GOTPC_HI16;
-
- case SH::fixup_copy:
- return ELF::R_SH_COPY;
-
- case SH::fixup_copy64:
- return ELF::R_SH_COPY64;
-
- case SH::fixup_glob_dat:
- return ELF::R_SH_GLOB_DAT;
-
- case SH::fixup_glob_dat64:
- return ELF::R_SH_GLOB_DAT64;
-
- case SH::fixup_jump_slot:
- return ELF::R_SH_JMP_SLOT;
-
- case SH::fixup_jump_slot64:
- return ELF::R_SH_JMP_SLOT64;
-
- case SH::fixup_relative:
- return ELF::R_SH_RELATIVE;
-
- case SH::fixup_relative64:
- return ELF::R_SH_RELATIVE64;
-
- case SH::fixup_dir32:
+ case SH::fixup_32:
return ELF::R_SH_DIR32;
- case SH::fixup_rel32:
- return ELF::R_SH_REL32;
-
- case SH::fixup_64:
- return ELF::R_SH_64;
-
- case SH::fixup_64_pcrel:
- return ELF::R_SH_64_PCREL;
-
default:
llvm_unreachable("invalid fixup kind!");
}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
index 821a588c3dd44..e965552f84ccd 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
@@ -17,140 +17,29 @@ namespace SH {
// clang-format off
/// The set of supported fixups.
-///
-/// Although most of the current fixup types reflect a unique relocation
-/// one can have multiple fixup types for a given relocation and thus need
-/// to be uniquely named.
-///
-/// \note This table *must* be in the same order of
-/// MCFixupKindInfo Infos[SuperH::NumTargetFixupKinds]
-/// in `SuperHAsmBackend.cpp`.
enum Fixups {
- // The following fields follow the instructions in the C ABI Specification
- // which can be found at https://www.renesas.com/en/document/mat/superh-cc-compiler-package-v904-users-manual?r=1169516
- //
- // NOTE: Some relocation names are misspelled in the official manual,
- // The misspellings are corrected as follows:
- // - R_SH_PLT_MEWLOW16 -> R_SH_PLT_MEDLOW16
- //
- // Name Value Field Calculation
+ fixup_32 = FirstTargetFixupKind,
+
+ /// A fixup that represents a PC-relative address scaled by 2.
+ fixup_pcrel4_by2,
- // R_SH_GOT32 160 word32 G + A
- fixup_got32 = FirstTargetFixupKind,
+ /// A fixup that represents a PC-relative address scaled by 4.
+ fixup_pcrel4_by4,
- // R_SH_GOT_LOW16 169 T_32s10for16 (G + A) & 65535
- fixup_got_low16,
+ /// A fixup that represents a PC-relative address scaled by 4.
+ fixup_pcrel8_by4,
- // R_SH_GOT_MEDLOW16 170 T_32u10for16 ((G + A) >> 16) & 65535
- fixup_got_medlow16,
+ /// A fixup that represents a PC-relative address scaled by 2,
+ /// with a 4-byte offset.
+ fixup_pcrel8_4by2,
- // R_SH_GOT_MEDHI16 171 T_32u10for16 ((G + A) >> 32) & 65535
- fixup_got_medhi16,
+ /// A fixup that represents a PC-relative address scaled by 4,
+ /// with a 4-byte offset.
+ fixup_pcrel8_4by4,
- // R_SH_GOT_HI16 172 T_32u10for16 ((G + A) >> 48) & 65535
- fixup_got_hi16,
-
- // R_SH_GOT10BY4 189 V_32s10for10 (G + A) / 4
- fixup_got10by4,
-
- // R_SH_GOT10BY8 191 V_32s10for10 (G + A) / 8
- fixup_got10by8,
-
- // R_SH_PLT32 161 word32 L + A - P
- fixup_plt32,
-
- // R_SH_PLT_LOW16 177 T_32s10for16 (L + A - P) & 65535
- fixup_plt_low16,
-
- // R_SH_PLT_MEDLOW16 178 T_32u10for16 ((L + A - P) >> 16) & 65535
- fixup_plt_medlow16,
-
- // R_SH_PLT_MEDHI16 179 T_32u10for16 ((L + A - P) >> 32) & 65535
- fixup_plt_medhi16,
-
- // R_SH_PLT_HI16 180 T_32u10for16 ((L + A - P) >> 48) & 65535
- fixup_plt_hi16,
-
- // R_SH_GOTPLT32 168 word32 G + A
- fixup_gotplt32,
-
- // R_SH_GOTPLT_LOW16 169 T_32s10for16 (G + A) & 65535
- fixup_gotplt_low16,
-
- // R_SH_GOTPLT_MEDLOW16 170 T_32u10for16 ((G + A) >> 16) & 65535
- fixup_gotplt_medlow16,
-
- // R_SH_GOTPLT_MEDHI16 171 T_32u10for16 ((G + A) >> 32) & 65535
- fixup_gotplt_medhi16,
-
- // R_SH_GOTPLT_HI16 172 T_32u10for16 ((G + A) >> 48) & 65535
- fixup_gotplt_hi16,
-
- // R_SH_GOTOFF 166 word32 S + A - GOT
- fixup_gotoff,
-
- // R_SH_GOTOFF_LOW16 181 T_32s10for16 (S + A - GOT) & 65535
- fixup_gotoff_low16,
-
- // R_SH_GOTOFF_MEDLOW16 182 T_32u10for16 ((S + A - GOT) >> 16) & 65535
- fixup_gotoff_medlow16,
-
- // R_SH_GOTOFF_MEDHI16 183 T_32u10for16 ((S + A - GOT) >> 32) & 65535
- fixup_gotoff_medhi16,
-
- // R_SH_GOTOFF_HI16 184 T_32u10for16 ((S + A - GOT) >> 48) & 65535
- fixup_gotoff_hi16,
-
- // R_SH_GOTPC 167 word32 GOT + A - P
- fixup_gotpc,
-
- // R_SH_GOTPC_LOW16 185 T_32s10for16 (GOT + A - P) & 65535
- fixup_gotpc_low16,
-
- // R_SH_GOTPC_MEDLOW16 186 T_32u10for16 ((GOT + A - P) >> 16) & 65535
- fixup_gotpc_medlow16,
-
- // R_SH_GOTPC_MEDHI16 187 T_32u10for16 ((GOT + A - P) >> 32) & 65535
- fixup_gotpc_medhi16,
-
- // R_SH_GOTPC_HI16 188 T_32u10for16 ((GOT + A - P) >> 48) & 65535
- fixup_gotpc_hi16,
-
- // R_SH_COPY 162 none none
- fixup_copy,
-
- // R_SH_COPY64 193 none none
- fixup_copy64,
-
- // R_SH_GLOB_DAT 163 word32 S
- fixup_glob_dat,
-
- // R_SH_GLOB_DAT64 194 word64 S
- fixup_glob_dat64,
-
- // R_SH_JMP_SLOT 164 word32 S
- fixup_jump_slot,
-
- // R_SH_JMP_SLOT64 195 word64 S
- fixup_jump_slot64,
-
- // R_SH_RELATIVE 165 word32 B + A
- fixup_relative,
-
- // R_SH_RELATIVE64 196 word64 B + A
- fixup_relative64,
-
- // R_SH_DIR32 1 word32 S + A
- fixup_dir32,
-
- // R_SH_REL32 2 word32 S + A - P
- fixup_rel32,
-
- // R_SH_64 254 word64 S + A
- fixup_64,
-
- // R_SH_64_PCREL 255 word64 S + A - P
- fixup_64_pcrel,
+ /// A fixup that represents a PC-relative address scaled by 2,
+ /// with a 4-byte offset.
+ fixup_pcrel12_4by2,
// Marker
LastTargetFixupKind,
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 690515d648564..1c8a76dcc7467 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -125,38 +125,58 @@ unsigned SuperHMCCodeEmitter::getOpBits(const MCInst &MI,
// the given opcode.
// This is neccesary due to the various opcodes that access memory
// have different scaling factors applied.
-static std::optional<MCFixup> getFixupForOpcode(unsigned Opcode, const MCExpr *Expr, MCContext &Ctx) {
- bool isOp32 = isOpcode32(Opcode) ? FK_Data_4 : FK_Data_2;
+static MCFixup getFixupForOpcode(unsigned Opcode, const MCExpr *Expr, MCContext &Ctx) {
+
+ // NOTE: A few (DSP and SH2A) instructions are 32-bits wide.
+ // We handle those quite crudely.
+ MCFixupKind Kind = isOpcode32(Opcode) ? FK_Data_4 : FK_Data_2;
switch(Opcode) {
default: break;
- // disp * 2
- case SH::BF:
- case SH::BFS:
- case SH::BT:
- case SH::BTS:
- case SH::BSR:
- case SH::BRA:
- case SH::MOVWI:
+ // disp4 * 2
case SH::MOVWL4:
case SH::MOVWLG:
case SH::MOVWS4:
case SH::MOVWSG:
- Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(2, Ctx), Ctx);
+ Kind = SH::fixup_pcrel4_by2;
break;
- // disp * 4
- case SH::MOVA:
- case SH::MOVLI:
- case SH::MOVLL4:
+ // disp4 * 4
case SH::MOVLLG:
case SH::MOVLS4:
case SH::MOVLSG:
- Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(4, Ctx), Ctx);
+ Kind = SH::fixup_pcrel4_by4;
+ break;
+
+ // disp8 * 4
+ case SH::MOVA:
+ Kind = SH::fixup_pcrel8_by4;
+ break;
+
+ // (disp8 * 2) + 4
+ case SH::BF:
+ case SH::BFS:
+ case SH::BT:
+ case SH::BTS:
+ case SH::MOVWI:
+ case SH::MOVLL4:
+ Kind = SH::fixup_pcrel8_4by2;
+ break;
+
+ // (disp8 * 4) + 4
+ case SH::MOVLI:
+ Kind = SH::fixup_pcrel8_4by4;
+ break;
+
+ // (disp12 * 2) + 4
+ case SH::BSR:
+ case SH::BRA:
+ Kind = SH::fixup_pcrel12_4by2;
break;
}
- return MCFixup::create(0, Expr, isOp32 ? FK_Data_4 : FK_Data_2, true);
+
+ return MCFixup::create(0, Expr, Kind, true);
}
void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
@@ -199,9 +219,7 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
if (!Expr)
return 0;
- MCExpr::ExprKind Kind = Expr->getKind();
-
- switch(Kind) {
+ switch(Expr->getKind()) {
case MCExpr::ExprKind::Binary: {
unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI);
Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI);
@@ -216,11 +234,7 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
return 0;
}
case MCExpr::ExprKind::SymbolRef: {
-
- // NOTE: A few (DSP and SH2A) instructions are 32-bits wide.
- // We handle those quite crudely.
- uint32_t OpCode = getOpBits(MI, Fixups, STI);
- Fixups.push_back(MCFixup::create(0, Expr, isOpcode32(OpCode) ? FK_Data_4 : FK_Data_2, true));
+ Fixups.push_back(getFixupForOpcode(MI.getOpcode(), Expr, Ctx));
return 0;
}
case MCExpr::ExprKind::Constant: {
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index 567fcc79a3e0d..e6665581e722e 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -29,7 +29,7 @@
using namespace llvm;
-#define DEBUG_TYPE "asm-printer"
+#define DEBUG_TYPE "sh-asm-printer"
namespace {
@@ -84,6 +84,7 @@ class SuperHAsmPrinter : public AsmPrinter {
} // namespace
bool SuperHAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+ LLVM_DEBUG(dbgs() << "***** SuperHAsmPrinter *****\n");
MCP = MF.getConstantPool();
return AsmPrinter::runOnMachineFunction(MF);
}
@@ -188,13 +189,24 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
const BlockAddress *BA =
cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
MCSym = GetBlockAddressSymbol(BA);
+
+ dbgs() << "Emit CPV BlockAddress " << SCPV->getLabelId()
+ << " \"" << MCSym->getName() << "\"...\n";
+
} else if (SCPV->isGlobalValue()) {
const GlobalValue *GV = cast<SuperHConstantPoolConstant>(SCPV)->getGV();
MCSym = getSymbolPreferLocal(*GV);
+
+ dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId()
+ << " \"" << MCSym->getName() << "\"...\n";
+
} else {
assert(SCPV->isExtSymbol() && "unrecognized constant pool value");
auto Sym = cast<SuperHConstantPoolSymbol>(SCPV)->getSymbol();
MCSym = GetExternalSymbolSymbol(Sym);
+
+ dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId()
+ << " \"" << MCSym->getName() << "\"...\n";
}
// Create an MCSymbol for the reference.
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
index cdedd3e8f634b..e102c2438a600 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
@@ -42,7 +42,7 @@ StringRef SuperHConstantPoolValue::getModifierText() const {
case SHCP::GOT_PCREL:
return "gotpcrel";
case SHCP::DIR:
- return "";
+ return "dir";
}
llvm_unreachable("Unknown modifier!");
}
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index ca9b1bebcabb5..f89a607502340 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -143,8 +143,6 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
auto DL = CurDAG->getDataLayout();
MVT PtrVT = getTargetLowering()->getPointerTy(DL);
- LLVM_DEBUG(dbgs() << "SelectAddr\n");
-
// if the address is a frame index get the TargetFrameIndex.
if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
@@ -170,28 +168,34 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
SDValue N0 = N->getOperand(0);
- // External Symbols
- if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
- SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
- ReplaceNode(N, Res);
- return true;
- }
-
// Global Addresses
- if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
- SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
- ReplaceNode(N, Res);
- return true;
+ if (GlobalAddressSDNode* GA = dyn_cast<GlobalAddressSDNode>(N0.getNode())) {
+ if (auto *CPV = SFI->tryGetConstant(GA, *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
+ ReplaceNode(N, Res);
+ return true;
+ }
}
// Block Addresses
- if (auto *CPV = SFI->tryGetConstant((BlockAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
- SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
- MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
- ReplaceNode(N, Res);
- return true;
+ if (BlockAddressSDNode* BA = dyn_cast<BlockAddressSDNode>(N0.getNode())) {
+ if (auto *CPV = SFI->tryGetConstant(BA, *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
+ ReplaceNode(N, Res);
+ return true;
+ }
+ }
+
+ // External Symbols
+ if (ExternalSymbolSDNode* Sym = dyn_cast<ExternalSymbolSDNode>(N0.getNode())) {
+ if (auto *CPV = SFI->tryGetConstant(Sym, *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
+ ReplaceNode(N, Res);
+ return true;
+ }
}
return false;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 78a63370a645e..6ea55fc313a75 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -200,8 +200,8 @@ SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
auto PtrVT = getPointerTy(DAG.getDataLayout());
auto DL = SDLoc(G);
- // SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
- SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0);
+ SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
+ SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, OpFlags);
return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
}
return SDValue();
@@ -218,7 +218,7 @@ SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG)
const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
- SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT);
+ SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags);
return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
}
return SDValue();
@@ -235,7 +235,7 @@ SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) c
const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
- SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT);
+ SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT, 0, OpFlags);
return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
}
return SDValue();
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index 157e06680e986..79451cd815e4a 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -22,29 +22,29 @@ SuperHMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
const SuperHSubtarget &Subtarget) const {
const MCExpr *Expr = nullptr;
switch (MO.getTargetFlags()) {
- case SHII::MO_NO_FLAG:
- Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
- break;
+ case SHII::MO_NO_FLAG:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
+ break;
- case SHII::MO_GOT:
- Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT, Ctx);
- break;
+ case SHII::MO_GOT:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT, Ctx);
+ break;
- case SHII::MO_GOTPC:
- Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_PCREL, Ctx);
- break;
+ case SHII::MO_GOTPC:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_PCREL, Ctx);
+ break;
- case SHII::MO_GOTOFF:
- Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_OFF, Ctx);
- break;
+ case SHII::MO_GOTOFF:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_OFF, Ctx);
+ break;
- case SHII::MO_DIR:
- Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
- break;
+ case SHII::MO_DIR:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
+ break;
- case SHII::MO_PCREL:
- Expr = MCSymbolRefExpr::create(Sym, SH::S_PCREL, Ctx);
- break;
+ case SHII::MO_PCREL:
+ Expr = MCSymbolRefExpr::create(Sym, SH::S_PCREL, Ctx);
+ break;
}
return MCOperand::createExpr(Expr);
}
>From 842a77823c02023f3d45938e681095c354336791 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 4 Sep 2026 04:33:48 +0200
Subject: [PATCH 36/39] Fix frame index elimination, add more clang scaffolding
---
clang/lib/CodeGen/CMakeLists.txt | 1 +
clang/lib/CodeGen/CodeGenModule.cpp | 5 +
clang/lib/CodeGen/TargetInfo.h | 3 +
clang/lib/CodeGen/Targets/SuperH.cpp | 93 +++++++++++
llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp | 12 +-
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 99 +++++++-----
llvm/lib/Target/SuperH/SuperHFrameLowering.h | 15 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 5 +-
.../Target/SuperH/SuperHMachineFunctionInfo.h | 3 +
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 148 +++++++++++++++---
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 1 -
llvm/lib/TargetParser/TargetDataLayout.cpp | 4 +-
12 files changed, 310 insertions(+), 79 deletions(-)
create mode 100644 clang/lib/CodeGen/Targets/SuperH.cpp
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 75b2f5826f863..af36f8fe2f32d 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -152,6 +152,7 @@ add_clang_library(clangCodeGen
Targets/RISCV.cpp
Targets/SPIR.cpp
Targets/Sparc.cpp
+ Targets/SuperH.cpp
Targets/SystemZ.cpp
Targets/TCE.cpp
Targets/VE.cpp
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index b8841f75a5c19..3418864aedebb 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -242,6 +242,11 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
bool EABI = ABIStr.ends_with("e");
return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
}
+
+ case llvm::Triple::sh:
+ case llvm::Triple::shl: {
+ return createSuperHTargetCodeGenInfo(CGM);
+ }
case llvm::Triple::systemz: {
bool SoftFloat = CodeGenOpts.FloatABI == "soft";
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index 89ea27b748aa9..f93683859e2aa 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -572,6 +572,9 @@ createSparcV8TargetCodeGenInfo(CodeGenModule &CGM);
std::unique_ptr<TargetCodeGenInfo>
createSparcV9TargetCodeGenInfo(CodeGenModule &CGM);
+std::unique_ptr<TargetCodeGenInfo>
+createSuperHTargetCodeGenInfo(CodeGenModule &CGM);
+
std::unique_ptr<TargetCodeGenInfo>
createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector,
bool SoftFloatABI);
diff --git a/clang/lib/CodeGen/Targets/SuperH.cpp b/clang/lib/CodeGen/Targets/SuperH.cpp
new file mode 100644
index 0000000000000..eae3cd39de190
--- /dev/null
+++ b/clang/lib/CodeGen/Targets/SuperH.cpp
@@ -0,0 +1,93 @@
+//===- SuperH.cpp ---------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABIInfoImpl.h"
+#include "TargetInfo.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/Support/MathExtras.h"
+
+using namespace clang;
+using namespace clang::CodeGen;
+
+//===----------------------------------------------------------------------===//
+// SuperH ABI Implementation. Documented at
+// https://llvm-gcc-renesas.com/manuals/SH-ABI-Specification.html
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SuperHABIInfo : public DefaultABIInfo {
+public:
+ SuperHABIInfo(CodeGenTypes &CGT)
+ : DefaultABIInfo(CGT) {}
+
+ ABIArgInfo classifyReturnType(QualType Ty, bool &LargeRet) const {
+
+ // We have a total of 64 bits of return space in R0 and R1,
+ // if we can fit a struct in there, do.
+ if (isAggregateTypeForABI(Ty) &&
+ getContext().getTypeSize(Ty) <= 64)
+ return ABIArgInfo::getDirect();
+
+ // Otherwise, we store a pointer to the struct in R2 and return that.
+ if (getContext().getTypeSize(Ty) > 64) {
+ LargeRet = true;
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+ }
+
+ // Otherwise we follow the default way which is compatible.
+ return DefaultABIInfo::classifyReturnType(Ty);
+ }
+
+ ABIArgInfo classifyArgumentType(QualType Ty, unsigned &NumRegs) const {
+ unsigned TySize = getContext().getTypeSize(Ty);
+
+ // Smaller types are required to be sign extended.
+ if (TySize < 32 && NumRegs > 0 && Ty->isIntegralOrEnumerationType()) {
+ NumRegs -= 1;
+ return ABIArgInfo::getExtend(Ty);
+ }
+
+ // If there's enough space, pass in registers.
+ if (TySize <= NumRegs * 32) {
+ NumRegs -= TySize / 32;
+ return ABIArgInfo::getDirect();
+ }
+
+ // A pointer will be created and passsed in R4 instead, as the arguments
+ // from here on out doesn't fit in the remaining registers.
+ NumRegs = 0;
+ return ABIArgInfo::getDirect();
+ }
+
+ void computeInfo(CGFunctionInfo &FI) const override {
+
+ // Decide the return type.
+ bool LargeRet = false;
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), LargeRet);
+
+ // Decide each argument type.
+ unsigned NumRegs = 4;
+ for (auto &I : FI.arguments())
+ I.info = classifyArgumentType(I.type, NumRegs);
+ }
+
+};
+
+class SuperHTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ SuperHTargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(std::make_unique<SuperHABIInfo>(CGT)) {}
+
+};
+}
+
+std::unique_ptr<TargetCodeGenInfo>
+CodeGen::createSuperHTargetCodeGenInfo(CodeGenModule &CGM) {
+ return std::make_unique<SuperHTargetCodeGenInfo>(CGM.getTypes());
+}
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index e6665581e722e..0baa06d54cfa7 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -190,23 +190,23 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
MCSym = GetBlockAddressSymbol(BA);
- dbgs() << "Emit CPV BlockAddress " << SCPV->getLabelId()
- << " \"" << MCSym->getName() << "\"...\n";
+ LLVM_DEBUG(dbgs() << "Emit CPV BlockAddress " << SCPV->getLabelId()
+ << " \"" << MCSym->getName() << "\"...\n");
} else if (SCPV->isGlobalValue()) {
const GlobalValue *GV = cast<SuperHConstantPoolConstant>(SCPV)->getGV();
MCSym = getSymbolPreferLocal(*GV);
- dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId()
- << " \"" << MCSym->getName() << "\"...\n";
+ LLVM_DEBUG(dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId()
+ << " \"" << MCSym->getName() << "\"...\n");
} else {
assert(SCPV->isExtSymbol() && "unrecognized constant pool value");
auto Sym = cast<SuperHConstantPoolSymbol>(SCPV)->getSymbol();
MCSym = GetExternalSymbolSymbol(Sym);
- dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId()
- << " \"" << MCSym->getName() << "\"...\n";
+ LLVM_DEBUG(dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId()
+ << " \"" << MCSym->getName() << "\"...\n");
}
// Create an MCSymbol for the reference.
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 5b3bd8840f0c7..32106d529a021 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -25,6 +25,7 @@
#include "llvm/MC/MCRegister.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugLog.h"
+#include "llvm/Support/TypeSize.h"
#include "llvm/Target/TargetMachine.h"
#include <cstdint>
@@ -130,49 +131,53 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
const MCContext &Ctx = MF.getContext();
DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
+ bool HasFP = hasFP(MF);
Register SP = RII.getStackRegister();
Register FP = RII.getFrameRegister();
Register GOT = RII.getGOTRegister();
- LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
+ // Reference register.
+ Register Ref = HasFP ? SP : FP;
- // Early exit if we have no frame pointer.
- if (!hasFP(MF)) {
- return;
- }
+ LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
// Realign stack to 32-bit offsets.
uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
MFI.setStackSize(StackSize);
-
- // Store GOT
- if (STI.isPositionIndependent()) {
- if (auto *GOTSym = MF.getPICBaseSymbol()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
- .addReg(GOT)
- .setMIFlag(MachineInstr::FrameSetup);
- }
- }
- // Establish Stack Frame
- // mov.l r14, at -r15
- // add <stackadj>,r15
- // mov r15,r14
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
- .addReg(FP)
- .setMIFlag(MachineInstr::FrameSetup);
- emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameSetup);
+ // Store previous frame pointer.
+ if (HasFP) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), FP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
- // Save return address to stack.
+ // Store Return address on stack (if needed)
if (MFI.hasCalls()) {
BuildMI(MBB, MBBI, DL, TII.get(SH::STSMPR))
.addReg(SP)
.setMIFlag(MachineInstr::FrameSetup);
+ BuildMI(MBB, MBBI, DL, TII.get(SH::ADDI), SP)
+ .addReg(SP)
+ .addImm(-4);
}
+
+ // Create new frame pointer.
+ if (HasFP) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
+
+ // // Store GOT
+ // if (STI.isPositionIndependent()) {
+ // if (auto *GOTSym = MF.getPICBaseSymbol()) {
+ // BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
+ // .addReg(GOT)
+ // .setMIFlag(MachineInstr::FrameSetup);
+ // }
+ // }
}
void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
@@ -239,6 +244,13 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
}
}
}
+
+void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
+ RegScavenger *RS) const {
+ LLVM_DEBUG(dbgs() << "determineCalleeSaves\n");
+ TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
+}
+
bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
@@ -260,7 +272,6 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
.addReg(Reg)
.setMIFlag(MachineInstr::FrameSetup);
}
-
return true;
}
@@ -279,7 +290,6 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
const TargetInstrInfo &TII = *STI.getInstrInfo();
Register SP = RII.getStackRegister();
-
for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
MCRegister Reg = I.getReg();
@@ -291,6 +301,25 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
return true;
}
+StackOffset
+SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
+ Register &FrameReg) const {
+ const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
+ const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
+ bool HasFP = hasFP(MF);
+
+ // R14 base
+ int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
+ if (HasFP) {
+ FrameReg = RegInfo->getFrameRegister();
+ return StackOffset::getFixed(FrameOffset);
+ }
+
+ // R15 base
+ FrameReg = RegInfo->getStackRegister(); // %sp
+ return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());
+}
+
MachineBasicBlock::iterator
SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
@@ -308,15 +337,6 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
if (Amount == 0) {
return MBB.erase(MI);
}
-
- DebugLoc DL = MI->getDebugLoc();
- unsigned int Opcode = MI->getOpcode();
- if (Opcode == TII.getCallFrameSetupOpcode()) {
-
- } else {
- assert(Opcode == TII.getCallFrameDestroyOpcode());
- }
-
return MBB.erase(MI);
}
@@ -336,9 +356,4 @@ bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
return hasFP(MF) && !MFI.hasVarSizedObjects();
-}
-
-void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
- RegScavenger *RS) const {
- TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index 66c3ff6eb6dce..0f8bc43b4f4ce 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -29,7 +29,7 @@ class SuperHFrameLowering : public TargetFrameLowering {
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
/*StackAlignment*/Align(4),
/*LocalAreaOffset*/0,
- /*TransAl*/Align(4),
+ /*TransAl*/Align(1),
/*StackReal*/false),
STI(STI) {}
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
@@ -41,13 +41,20 @@ class SuperHFrameLowering : public TargetFrameLowering {
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
+
+ void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
+ RegScavenger *RS) const override;
+
+ /// getFrameIndexReference - This method should return the base register
+ /// and offset used to reference a frame index location. The offset is
+ /// returned directly, and the base register is returned via FrameReg.
+ StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
+ Register &FrameReg) const override;
+
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const override;
-
- void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
- RegScavenger *RS) const override;
protected:
bool hasFPImpl(const MachineFunction &MF) const override;
};
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index e65d05a4c2276..35447696b9a20 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -126,7 +126,6 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
Register DestReg, Register SrcReg, bool KillSrc,
bool RenamableDest,
bool RenamableSrc) const {
-
// Do nothing, self copy.
if (SrcReg == DestReg)
return;
@@ -259,6 +258,8 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
}
Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+ LLVM_DEBUG(dbgs() << "isLoadFromStackSlot\n");
+
if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
FrameIndex = MI.getOperand(1).getIndex();
@@ -268,6 +269,8 @@ Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &Frame
}
Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+ LLVM_DEBUG(dbgs() << "isStoreToStackSlot\n");
+
if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
MI.getOperand(1).getImm() == 0) {
FrameIndex = MI.getOperand(0).getIndex();
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
index 33264e71670a0..c330e0b4ec931 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -15,6 +15,7 @@
#define LLVM_LIB_TARGET_SUPERH_SUPERHMACHINEFUNCTION_H
#include "SuperHConstantPoolValue.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Register.h"
@@ -28,6 +29,8 @@ class SuperHMachineFunctionInfo : public MachineFunctionInfo {
/// CPIndexCount - How many constant pool indices are allocated.
unsigned CPIndexCount = 0;
+ BitVector UsedRegs;
+
public:
explicit SuperHMachineFunctionInfo(const Function &F,
const TargetSubtargetInfo *STI) {}
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index b861431ca934d..75f42e2b29467 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -19,6 +19,8 @@
#include "SuperH.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
@@ -85,12 +87,40 @@ BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
return Reserved;
}
+/// getLoadBaseOffset - Gets the base offset to emit a load/store from.
+static int64_t getLoadStoreBaseOffset(unsigned Opcode) {
+ switch(Opcode) {
+ case SH::MOVBL4:
+ case SH::MOVBS4:
+ return 12;
+
+ case SH::MOVWL4:
+ case SH::MOVWS4:
+ return 28;
+
+ case SH::MOVLS4:
+ case SH::MOVLL4:
+ return 60;
+
+ default:
+ return 0;
+ }
+}
+
+static void replaceFI(const MachineFunction &MF, MachineBasicBlock::iterator II,
+ MachineInstr &MI, const DebugLoc &dl,
+ unsigned FIOperandNum, int Offset, Register FramePtr) {
+
+ MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
+ MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
+}
+
bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS) const {
MachineInstr &MI = *II;
- DebugLoc dl = MI.getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
MachineBasicBlock &MBB = *MI.getParent();
const MachineFunction &MF = *MBB.getParent();
const MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -99,33 +129,105 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
const TargetInstrInfo &TII = *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
- int64_t Size = MFI.getObjectSize(FrameIndex);
- int64_t StackSize = MFI.getStackSize() + 8;
- int64_t Offset = MFI.getObjectOffset(FrameIndex);
-
- // Add 4 to offset because SP points to saved FP
- Offset += StackSize - TFI->getOffsetOfLocalArea() + 4;
-
- // Fold incoming offset.
- Offset += MI.getOperand(FIOperandNum + 1).getImm();
+ dbgs() << FrameIndex << " " << TII.getName(MI.getDesc().getOpcode()) << "\n";
+
+ // Get the register offset to fetch.
+ Register FrameReg;
+ int64_t Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
+ Offset += MFI.getStackSize();
+
+ int64_t ROff = getLoadStoreBaseOffset(MI.getOpcode());
+
+ // Handle frame loads and stores.
+ switch(MI.getOpcode()) {
+
+ // Stack Store
+ case SH::MOVBS4:
+ case SH::MOVWS4: {
+ Register SrcReg = MI.getOperand(0).getReg();
+
+ MI.dump();
+ dbgs() << "\n";
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov <src reg>, r0
+ // mov.w/b r0,@(ROff+Offset,r1)
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-ROff);
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R0)
+ .addReg(SrcReg);
+
+ Offset = ROff+Offset;
+ FrameReg = SH::R1;
+ break;
+ }
+ case SH::MOVLS4: {
+
+ MI.dump();
+ dbgs() << "\n";
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov.l <src reg>,@(ROff+Offset,r1)
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-ROff);
+ Offset = ROff+Offset;
+ FrameReg = SH::R1;
+ break;
+ }
- if (MI.getOpcode() == SH::SHFrmIdx) {
+ // Stack Load
+ case SH::MOVBL4:
+ case SH::MOVWL4: {
Register DstReg = MI.getOperand(0).getReg();
- // mov r14,r1
- // add #-<frame size>,r1
- BuildMI(MBB, MI, DebugLoc(), TII.get(SH::MOV), DstReg)
- .addReg(SH::R14);
- BuildMI(MBB, MI, DebugLoc(), TII.get(SH::ADDI), DstReg)
- .addReg(DstReg)
- .addImm(-StackSize);
-
- II++;
- MI.eraseFromParent();
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov.w/b @(ROff+Offset,r1),r0
+ // mov r0,<dst reg>
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-ROff);
+
+ // This inserts it after our instruction
+ BuildMI(*MI.getParent(), MI, DL, TII.get(SH::ADDI), DstReg)
+ .addReg(SH::R0)
+ .addImm(-ROff);
+
+ Offset = ROff+Offset;
+ FrameReg = SH::R1;
+ break;
+ }
+ case SH::MOVLL4: {
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov.l @(ROff+Offset,r1),<dst reg>
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-ROff);
+ Offset = ROff+Offset;
+ FrameReg = SH::R1;
+ break;
+ }
}
- MI.getOperand(FIOperandNum).ChangeToRegister(SH::R1, false);
- MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
+ replaceFI(MF, II, MI, DL, FIOperandNum, Offset, FrameReg);
return false;
}
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 86a4a4c41bd85..c39f3d643d94f 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -96,7 +96,6 @@ SuperHTargetMachine::SuperHTargetMachine(const Target &T, const Triple &TT,
RM.value_or(Reloc::Static),
getEffectiveCodeModel(CM, CodeModel::Small),
OL), TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
-
initAsmInfo();
}
diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp
index 2dc69abf12064..a71bbec8219d3 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -555,10 +555,10 @@ static std::string computeVEDataLayout(const Triple &T) {
static std::string computeSuperHDataLayout(const Triple &T) {
// Mixed-endian
- std::string Ret = T.getArch() == Triple::shl ? "e" : "E";
+ std::string Ret = T.isLittleEndian() ? "e" : "E";
// ELF name manging
- Ret += "-m:e";
+ Ret += getManglingComponent(T);
// 32-bit pointers, 32 bit aligned
Ret += "-p:32:32";
>From 67a4173bf51b398cf63e2e193f5c9b48eafd8876 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 4 Sep 2026 07:37:50 +0200
Subject: [PATCH 37/39] Fix stack-frame & frame-index lowering
---
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 242 +++++++++---------
llvm/lib/Target/SuperH/SuperHFrameLowering.h | 2 +
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 42 ++-
3 files changed, 154 insertions(+), 132 deletions(-)
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 32106d529a021..fe6003e7244ae 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -25,6 +25,7 @@
#include "llvm/MC/MCRegister.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugLog.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TypeSize.h"
#include "llvm/Target/TargetMachine.h"
#include <cstdint>
@@ -37,6 +38,13 @@ AccumOutgoingArgs("sh-accumulate-outgoing-args", cl::Hidden, cl::init(false),
using namespace llvm;
+
+
+
+//===--------------------------------------------------------------------------===//
+// Helpers
+//===--------------------------------------------------------------------------===//
+
// Get amount of times to shift the value in a SP adjustment
// for it to fit.
static unsigned getShiftAmt(uint32_t Val) {
@@ -48,50 +56,42 @@ static unsigned getShiftAmt(uint32_t Val) {
return R;
}
+/// adjustFrameOffsetDown - Helper that adjusts frame offset
+/// down.
+static void adjustFrameOffsetDown(int64_t &FrameOffset) {
+ FrameOffset -= 4;
+ if (FrameOffset < 0)
+ FrameOffset = 0;
+}
+
// Helper to emit stack pointer adjustment.
-static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int32_t AdjValue) {
- DebugLoc dl;
+void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI, int32_t AdjValue) const {
const SuperHInstrInfo &TII = *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
- const SuperHRegisterInfo &RII = *static_cast<const SuperHRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
MachineInstr::MIFlag MFlag = AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
+ DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
// No stack frame allocation neccesary.
if (AdjValue == 0)
- return false;
-
- Register SP = RII.getStackRegister();
- Register FP = RII.getFrameRegister();
-
- if (abs(AdjValue) < 255) {
-
- if (AdjValue < 0) {
-
- // Fast path, emit a single immediate add.
- // Emit add #-(size),r15
- BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI), SP)
- .addReg(SP)
- .addImm((int)AdjValue);
- return true;
- }
-
- if (AdjValue > 0) {
+ return;
- // Fast path, emit a single immediate add.
- // Emit add #(size),r14
- BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI), FP)
- .addReg(FP)
- .addImm((int)AdjValue);
- return true;
- }
+ // Check if the adjustment can fit in an 8-bit immediate.
+ if (isInt<8>(AdjValue)) {
+ // Fast path, emit a single immediate add.
+ BuildMI(MBB, MBBI, DL, TII.get(SH::ADDI), Base)
+ .addReg(Base)
+ .addImm(AdjValue);
+ return;
}
+ // TODO: Embed a constant instead?
+
// Slow path, shift 8 bits at a time into r0.
unsigned ToShift = getShiftAmt(AdjValue);
// Empty R0 in case it had something.
- BuildMI(MBB, MBBI, dl, TII.get(SH::MOVI), SH::R0)
- .addImm(0)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::XOR), SH::R0)
.addReg(SH::R0)
.setMIFlag(MFlag);
@@ -99,52 +99,85 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasic
// or #(byte), r0
// shll8 r0
for(unsigned i = 0; i < ToShift; i++) {
- BuildMI(MBB, MBBI, dl, TII.get(SH::ORI))
+ BuildMI(MBB, MBBI, DL, TII.get(SH::ORI))
.addImm((AdjValue >> (i*8)) & 0xFF)
.setMIFlag(MFlag);
- BuildMI(MBB, MBBI, dl, TII.get(SH::SHLL8), SH::R0)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::SHLL8), SH::R0)
.addReg(SH::R0)
.setMIFlag(MFlag);
}
// Finally negate and add to r15.
// neg r0, r0 (if negative displacement)
- // add r0, r15
+ // add r0, <base>
if (AdjValue < 0)
- BuildMI(MBB, MBBI, dl, TII.get(SH::NEG), SH::R0)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::NEG), SH::R0)
.addReg(SH::R0)
.addReg(SH::R0)
.setMIFlag(MFlag);
- BuildMI(MBB, MBBI, dl, TII.get(SH::SUB), SP)
+ BuildMI(MBB, MBBI, DL, TII.get(SH::SUB), Base)
.addReg(SH::R0, RegState::Kill)
- .addReg(SP)
+ .addReg(Base)
.setMIFlag(MFlag);
- return true;
}
+StackOffset
+SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
+ Register &FrameReg) const {
+ const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
+ const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
+ bool HasFP = hasFP(MF);
+
+ // NOTE: All the frame indices are relative to the stack/frame pointer
+ // post-offset. as such an extra adjustment is needed here.
+ int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
+ FrameOffset += MFI.getStackSize() - TFI->getOffsetOfLocalArea();
+
+ // Adjust down to remove SP.
+ adjustFrameOffsetDown(FrameOffset);
+
+ // R14 base
+ if (HasFP) {
+
+ // Adjust down to remove FP.
+ adjustFrameOffsetDown(FrameOffset);
+ FrameReg = RegInfo->getFrameRegister();
+ return StackOffset::getFixed(FrameOffset);
+ }
+
+ // R15 base
+ FrameReg = RegInfo->getStackRegister(); // r15
+ return StackOffset::getFixed(FrameOffset);
+}
+
+
+
+
+//===--------------------------------------------------------------------------===//
+// Prologue/Epilogue Emission
+//===--------------------------------------------------------------------------===//
+
void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+ LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
+
MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo &MFI = MF.getFrameInfo();
const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
const SuperHInstrInfo &TII = *STI.getInstrInfo();
const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
const MCContext &Ctx = MF.getContext();
- DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
- bool HasFP = hasFP(MF);
-
Register SP = RII.getStackRegister();
Register FP = RII.getFrameRegister();
Register GOT = RII.getGOTRegister();
+ DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
+ bool HasFP = hasFP(MF);
- // Reference register.
- Register Ref = HasFP ? SP : FP;
-
- LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
-
- // Realign stack to 32-bit offsets.
- uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
- MFI.setStackSize(StackSize);
+ // Get stack frame size.
+ int64_t StackSize = MFI.getStackSize();
+ adjustFrameOffsetDown(StackSize);
// Store previous frame pointer.
if (HasFP) {
@@ -158,12 +191,10 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
BuildMI(MBB, MBBI, DL, TII.get(SH::STSMPR))
.addReg(SP)
.setMIFlag(MachineInstr::FrameSetup);
- BuildMI(MBB, MBBI, DL, TII.get(SH::ADDI), SP)
- .addReg(SP)
- .addImm(-4);
}
- // Create new frame pointer.
+ // Create new stack frame.
+ emitFrameAdjust(SP, MF, MBB, MBBI, -StackSize);
if (HasFP) {
BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
.addReg(SP)
@@ -181,69 +212,55 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
}
void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+ LLVM_DEBUG(dbgs() << "Emitting epilogue...\n");
+
+ MachineBasicBlock::iterator MBBI = MBB.begin();
const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+ const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+ const SuperHInstrInfo &TII = *STI.getInstrInfo();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
Register SP = RII.getStackRegister();
Register FP = RII.getFrameRegister();
+ DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
+ bool HasFP = hasFP(MF);
- LLVM_DEBUG(dbgs() << "Emitting epilogue...\n");
+ // Get stack frame size.
+ int64_t StackSize = MFI.getStackSize();
+ adjustFrameOffsetDown(StackSize);
- // Early exit if we have no frame pointer.
- if (!hasFP(MF)) {
- return;
+ // Restore stack frame
+ if (HasFP) {
+ emitFrameAdjust(FP, MF, MBB, MBBI, StackSize);
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), SP)
+ .addReg(FP)
+ .setMIFlag(MachineInstr::FrameSetup);
+ } else {
+ emitFrameAdjust(SP, MF, MBB, MBBI, StackSize);
}
- MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
- MachineFrameInfo &MFI = MF.getFrameInfo();
- DebugLoc DL = MBBI->getDebugLoc();
- const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
- const SuperHInstrInfo &TII = *STI.getInstrInfo();
+ // Restore return address from stack (if needed.)
+ if (MFI.hasCalls()) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ }
- uint32_t StackSize = MFI.getStackSize();
+ // Restore stack pointer
+ if (HasFP) {
+ BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLP), FP)
+ .addReg(SP)
+ .setMIFlag(MachineInstr::FrameDestroy);
+ }
- if (STI.isPositionIndependent()) {
+ // TODO: Handle GOT
+}
- // 1. Restore return address from stack.
- if (MFI.hasCalls()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameDestroy);
- }
- // 2. Delete stack frame, restoring stack pointer.
- if (StackSize > 0) {
- emitSPAdj(MF, MBB, MBBI, StackSize);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameDestroy);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
- .addReg(FP)
- .setMIFlag(MachineInstr::FrameDestroy);
- }
- } else {
- // 1. Restore return address from stack.
- if (MFI.hasCalls()) {
- BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameDestroy);
- }
-
- // 2. Delete stack frame, restoring stack pointer.
- // add <stackadj>,r14
- // mov r14,r15
- // mov.l @r15+,r14
- if (StackSize > 0) {
- emitSPAdj(MF, MBB, MBBI, StackSize);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
- .addReg(SP)
- .setMIFlag(MachineInstr::FrameDestroy);
- BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
- .addReg(FP)
- .setMIFlag(MachineInstr::FrameDestroy);
- }
- }
-}
+//===--------------------------------------------------------------------------===//
+// Callee-Saves
+//===--------------------------------------------------------------------------===//
void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const {
@@ -301,24 +318,12 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
return true;
}
-StackOffset
-SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
- Register &FrameReg) const {
- const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
- const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
- bool HasFP = hasFP(MF);
- // R14 base
- int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
- if (HasFP) {
- FrameReg = RegInfo->getFrameRegister();
- return StackOffset::getFixed(FrameOffset);
- }
- // R15 base
- FrameReg = RegInfo->getStackRegister(); // %sp
- return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());
-}
+
+//===--------------------------------------------------------------------------===//
+// Call-Frame Meta
+//===--------------------------------------------------------------------------===//
MachineBasicBlock::iterator
SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
@@ -342,6 +347,7 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
bool SuperHFrameLowering::canSimplifyCallFramePseudos(
const MachineFunction &MF) const {
+
// Always simplify call frame pseudo instructions, even when
// hasReservedCallFrame is false.
return true;
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index 0f8bc43b4f4ce..eed0b6194cc49 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -44,6 +44,8 @@ class SuperHFrameLowering : public TargetFrameLowering {
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const override;
+
+ void emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int32_t AdjValue) const;
/// getFrameIndexReference - This method should return the base register
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 75f42e2b29467..86867e04273b2 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -107,6 +107,27 @@ static int64_t getLoadStoreBaseOffset(unsigned Opcode) {
}
}
+/// getLoadBaseOffset - Gets the neccesary bit shift amount for the
+/// load/store indexing
+static int64_t getLoadStoreOffsetShift(unsigned Opcode) {
+ switch(Opcode) {
+ case SH::MOVBL4:
+ case SH::MOVBS4:
+ return 0;
+
+ case SH::MOVWL4:
+ case SH::MOVWS4:
+ return 1;
+
+ case SH::MOVLS4:
+ case SH::MOVLL4:
+ return 2;
+
+ default:
+ return 0;
+ }
+}
+
static void replaceFI(const MachineFunction &MF, MachineBasicBlock::iterator II,
MachineInstr &MI, const DebugLoc &dl,
unsigned FIOperandNum, int Offset, Register FramePtr) {
@@ -129,14 +150,11 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
const TargetInstrInfo &TII = *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
- dbgs() << FrameIndex << " " << TII.getName(MI.getDesc().getOpcode()) << "\n";
-
// Get the register offset to fetch.
Register FrameReg;
int64_t Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
- Offset += MFI.getStackSize();
-
int64_t ROff = getLoadStoreBaseOffset(MI.getOpcode());
+ int64_t Shift = getLoadStoreOffsetShift(MI.getOpcode());
// Handle frame loads and stores.
switch(MI.getOpcode()) {
@@ -145,9 +163,6 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
case SH::MOVBS4:
case SH::MOVWS4: {
Register SrcReg = MI.getOperand(0).getReg();
-
- MI.dump();
- dbgs() << "\n";
// Expand sequence to
// mov <base reg>,r1
@@ -162,15 +177,12 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R0)
.addReg(SrcReg);
- Offset = ROff+Offset;
+ Offset = (ROff-Offset) >> Shift;
FrameReg = SH::R1;
break;
}
case SH::MOVLS4: {
- MI.dump();
- dbgs() << "\n";
-
// Expand sequence to
// mov <base reg>,r1
// add #-ROff,r1
@@ -180,7 +192,8 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
.addReg(SH::R1)
.addImm(-ROff);
- Offset = ROff+Offset;
+
+ Offset = (ROff-Offset) >> Shift;
FrameReg = SH::R1;
break;
}
@@ -206,7 +219,7 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
.addReg(SH::R0)
.addImm(-ROff);
- Offset = ROff+Offset;
+ Offset = (ROff-Offset) >> Shift;
FrameReg = SH::R1;
break;
}
@@ -221,7 +234,8 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
.addReg(SH::R1)
.addImm(-ROff);
- Offset = ROff+Offset;
+
+ Offset = (ROff-Offset) >> Shift;
FrameReg = SH::R1;
break;
}
>From 3e46ecc035ac4a74305433224bba48d4a8c4a994 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 4 Sep 2026 16:22:10 +0200
Subject: [PATCH 38/39] Spill large constants to constpool
---
llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp | 20 +++-
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 11 ++-
llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 9 +-
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 94 +++++++++++++++----
llvm/lib/Target/SuperH/SuperHISelLowering.h | 1 +
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 2 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 30 +++++-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 35 ++++---
.../SuperH/SuperHMachineFunctionInfo.cpp | 33 +++++++
.../Target/SuperH/SuperHMachineFunctionInfo.h | 1 +
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 10 +-
11 files changed, 192 insertions(+), 54 deletions(-)
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index 0baa06d54cfa7..7ae610276fbf4 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -47,6 +47,11 @@ class SuperHAsmPrinter : public AsmPrinter {
/// pool entries so we can properly mark them as data regions.
bool InConstantPool = false;
+ /// Set of globals in PromotedGlobals that we've emitted labels for.
+ /// We need to emit labels even for promoted globals so that DWARF
+ /// debug info can link properly.
+ SmallPtrSet<const GlobalVariable*,2> EmittedPromotedGlobalLabels;
+
SuperHTargetStreamer &getTargetStreamer() {
return static_cast<SuperHTargetStreamer &>(
*OutStreamer->getTargetStreamer());
@@ -183,8 +188,21 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
if (Size < 4)
Size = 4;
- MCSymbol *MCSym;
+ // Handle promoted constants (eg. immediates that don't fit in 8 bits).
SuperHConstantPoolValue *SCPV = static_cast<SuperHConstantPoolValue*>(MCPV);
+ if (SCPV->isPromotedGlobal()) {
+ auto *SCPC = cast<SuperHConstantPoolConstant>(SCPV);
+ for (const auto *GV : SCPC->promotedGlobals()) {
+ if (!EmittedPromotedGlobalLabels.count(GV)) {
+ MCSymbol *GVSym = getSymbol(GV);
+ OutStreamer->emitLabel(GVSym);
+ EmittedPromotedGlobalLabels.insert(GV);
+ }
+ }
+ return emitGlobalConstant(DL, SCPC->getPromotedGlobalInit());
+ }
+
+ MCSymbol *MCSym;
if (SCPV->isBlockAddress()) {
const BlockAddress *BA =
cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index fe6003e7244ae..834422c8419c1 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -161,7 +161,7 @@ SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
//===--------------------------------------------------------------------------===//
void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
- LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
+ LLVM_DEBUG(dbgs() << "Emitting prologue for " << MF.getName() << "...\n");
MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -181,6 +181,7 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
// Store previous frame pointer.
if (HasFP) {
+ adjustFrameOffsetDown(StackSize);
BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), FP)
.addReg(SP)
.setMIFlag(MachineInstr::FrameSetup);
@@ -212,9 +213,9 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
}
void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
- LLVM_DEBUG(dbgs() << "Emitting epilogue...\n");
+ LLVM_DEBUG(dbgs() << "Emitting epilogue for " << MF.getName() << "...\n");
- MachineBasicBlock::iterator MBBI = MBB.begin();
+ MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
const SuperHInstrInfo &TII = *STI.getInstrInfo();
@@ -223,6 +224,7 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
Register FP = RII.getFrameRegister();
DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
bool HasFP = hasFP(MF);
+
// Get stack frame size.
int64_t StackSize = MFI.getStackSize();
@@ -230,6 +232,7 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
// Restore stack frame
if (HasFP) {
+ adjustFrameOffsetDown(StackSize);
emitFrameAdjust(FP, MF, MBB, MBBI, StackSize);
BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), SP)
.addReg(FP)
@@ -264,7 +267,6 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const {
- LLVM_DEBUG(dbgs() << "determineCalleeSaves\n");
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
}
@@ -342,6 +344,7 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
if (Amount == 0) {
return MBB.erase(MI);
}
+
return MBB.erase(MI);
}
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index f89a607502340..e6822a465acca 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -198,6 +198,14 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
}
}
+ if (ConstantSDNode* Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
+ if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
+ SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+ MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
+ ReplaceNode(N, Res);
+ return true;
+ }
+ }
return false;
}
@@ -305,7 +313,6 @@ bool SuperHDAGToDAGISel::trySelectBRCOND(SDNode *N) {
-
//===----------------------------------------------------------------------===//
// Branch Lowering
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 6ea55fc313a75..06e7ea01b9c7f 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -79,7 +79,6 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setTruncStoreAction(VT, MVT::i1, Promote);
}
-
// Division and remainders are multi-instruction sequences
// on SuperH. Use a custom pass to lower those.
for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
@@ -90,7 +89,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
}
// Multiplies have multiple lowerings depending on size.
- for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
+ for (MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64}) {
setOperationAction(ISD::MUL, VT, Custom);
}
@@ -98,7 +97,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
-
+ setOperationAction(ISD::Constant, MVT::i32, Custom);
setOperationAction(ISD::BR_CC, MVT::i8, Custom);
setOperationAction(ISD::BR_CC, MVT::i16, Custom);
@@ -115,6 +114,10 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SETCC, MVT::i32, Custom);
setOperationAction(ISD::SETCC, MVT::i64, Custom);
+ // for (MVT VT : MVT::integer_valuetypes()) {
+ // setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Expand);
+ // }
+
setBooleanContents(ZeroOrOneBooleanContent);
setBooleanVectorContents(ZeroOrOneBooleanContent);
setJumpIsExpensive(false);
@@ -188,6 +191,32 @@ SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
+//===----------------------------------------------------------------------===//
+// CONSTANT LOWERING
+//===----------------------------------------------------------------------===//
+
+SDValue SuperHTargetLowering::LowerConstant(SDValue Op, SelectionDAG &DAG) const {
+ DEBUG_FN_PRINT()
+
+ // Get the address of the target into a register
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
+ auto DL = SDLoc(C);
+
+ // Constant would fit in immediate
+ if (isInt<8>(C->getSExtValue())) {
+ return Op;
+ }
+
+ // Constant would NOT fit in immediate, lower to constpool.
+ SDValue Const = DAG.getSignedTargetConstant(C->getSExtValue(), DL, C->getValueType(0));
+ return DAG.getNode(SHISD::WRAPPER, DL, C->getValueType(0), Const);
+ }
+ return SDValue();
+}
+
+
+
+
//===----------------------------------------------------------------------===//
// ADDRESS LOWERING
//===----------------------------------------------------------------------===//
@@ -255,16 +284,13 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
SmallVectorImpl<SDValue> &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo &MFI = MF.getFrameInfo();
- MachineRegisterInfo &RegInfo = MF.getRegInfo();
DataLayout DL = DAG.getDataLayout();
EVT PtrVT = getPointerTy(DAG.getDataLayout());
-
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext());
CCInfo.AnalyzeFormalArguments(Ins, CC_SH);
-
SDValue ArgValue;
for (CCValAssign &VA : ArgLocs) {
@@ -432,6 +458,14 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
*DAG.getContext());
+ // Resolve the global value to jump to.
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+ Callee = LowerGlobalAddress(SDValue(G, 0), DAG);
+ } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
+ Callee = LowerExternalSymbol(SDValue(S, 0), DAG);
+ }
+ CCInfo.AnalyzeCallOperands(Outs, CC_SH);
+
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getStackSize();
Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL);
@@ -445,6 +479,26 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
EVT RegVT = VA.getLocVT();
SDValue Arg = OutVals[AI];
+ // Promote the value if needed. With Clang this should not happen.
+ switch (VA.getLocInfo()) {
+ default:
+ llvm_unreachable("Unknown loc info!");
+ case CCValAssign::Full:
+ break;
+ case CCValAssign::SExt:
+ Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, RegVT, Arg);
+ break;
+ case CCValAssign::ZExt:
+ Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, RegVT, Arg);
+ break;
+ case CCValAssign::AExt:
+ Arg = DAG.getNode(ISD::ANY_EXTEND, DL, RegVT, Arg);
+ break;
+ case CCValAssign::BCvt:
+ Arg = DAG.getNode(ISD::BITCAST, DL, RegVT, Arg);
+ break;
+ }
+
// Stop when we encounter a stack argument, we need to process them
// in reverse order in the loop below.
if (VA.isMemLoc()) {
@@ -495,14 +549,6 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
InGlue = Chain.getValue(1);
}
- // Resolve the global value to jump to.
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- Callee = LowerGlobalAddress(SDValue(G, 0), DAG);
- } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
- Callee = LowerExternalSymbol(SDValue(S, 0), DAG);
- }
- InGlue = Chain.getValue(1);
-
// Returns a chain & a flag for retval copy to use.
SmallVector<SDValue, 8> Ops;
Ops.push_back(Chain);
@@ -633,6 +679,7 @@ SDValue SuperHTargetLowering::LowerDIV(SDValue Op, SelectionDAG &DAG) const {
//===----------------------------------------------------------------------===//
// MULTIPLICATION LOWERING
//===----------------------------------------------------------------------===//
+
SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
unsigned Opcode = Op->getOpcode();
assert((Opcode == ISD::MUL) && "Invalid opcode for MUL lowering");
@@ -644,17 +691,24 @@ SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
switch (VT.getSimpleVT().SimpleTy) {
default:
llvm_unreachable("Unexpected type for ");
+
case MVT::i8: {
- SDValue MulOp = DAG.getNode(SH::MULS, DL, MVT::i32, Op.getValue(0), Op.getValue(1));
- return DAG.getNode(SH::LDSMACL, DL, MVT::i32, MulOp);
+ MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+ return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
}
+
case MVT::i16: {
- SDValue MulOp = DAG.getNode(SH::MULS, DL, MVT::i32, Op.getValue(0), Op.getValue(1));
- return DAG.getNode(SH::LDSMACL, DL, MVT::i32, MulOp);
+ MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+ return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
}
case MVT::i32: {
- // 32-bit multiplication requires lowering to __mulsi3
+ MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+ return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
+ }
+
+ case MVT::i64: {
+ // 64-bit multiplication requires lowering to __mulsi3
SDValue InChain = DAG.getEntryNode();
TargetLowering::ArgListTy Args;
@@ -701,6 +755,8 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
return LowerDIV(Op, DAG);
case ISD::MUL:
return LowerMUL(Op, DAG);
+ case ISD::Constant:
+ return LowerConstant(Op, DAG);
case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG);
case ISD::ExternalSymbol:
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index a7b29f3640372..0d73e0749958d 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -65,6 +65,7 @@ class SuperHTargetLowering : public TargetLowering {
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerConstant(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerDIV(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index e8624d62397e5..5323f226da3a1 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -126,7 +126,7 @@ class InstRmRn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
// Opcode
let Opcode = opcode;
- let Inst{15-11} = Opcode{15-11};
+ let Inst{15-12} = Opcode{15-12};
let Inst{3-0} = Opcode{3-0};
// Operands
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 35447696b9a20..4b56c54fd9a44 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -118,7 +118,7 @@ const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
//===----------------------------------------------------------------------===//
-// Stack Frames
+// Register Managment.
//===----------------------------------------------------------------------===//
void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
@@ -130,6 +130,20 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
if (SrcReg == DestReg)
return;
+ // Load from MACL
+ if (SrcReg == SH::MACLO && SH::GPRRegClass.contains(DestReg)) {
+ BuildMI(MBB, MI, DL, get(SH::STSMACL), DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc));
+ return;
+ }
+
+ // Store to MACL
+ if (SH::GPRRegClass.contains(SrcReg) && DestReg == SH::MACLO) {
+ BuildMI(MBB, MI, DL, get(SH::LDSMACL), DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc));
+ return;
+ }
+
// If the targets are GPR registers, use MOV Rm, Rn.
if (SH::GPRRegClass.contains(DestReg, SrcReg)) {
BuildMI(MBB, MI, DL, get(SH::MOV), DestReg)
@@ -141,6 +155,14 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
llvm_unreachable("Impossible reg-to-reg copy");
}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Stack Frames
+//===----------------------------------------------------------------------===//
+
void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
Register SrcReg, bool isKill, int FrameIndex,
const TargetRegisterClass *RC, Register VReg,
@@ -354,10 +376,10 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
MBB.isLayoutSuccessor(TargetBB)) {
BranchCode = getOppositeCondCode(BranchCode);
- unsigned JNCC = getBrCond(BranchCode).getOpcode();
- MachineBasicBlock::iterator OldInst = I;
+ auto JNCC = getBrCond(BranchCode);
- BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
+ MachineBasicBlock::iterator OldInst = I;
+ BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), JNCC)
.addMBB(UnCondBrIter->getOperand(0).getMBB());
BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SH::BRA))
.addMBB(TargetBB);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 7e1c22e132a61..766d6199fb376 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -128,13 +128,18 @@ class SHRegIndirectClass<string op> : SHOpClass<"IReg" # op> {
// Immediate
class SHImmOp<int width, ValueType vt>
- : Operand<vt> {
+ : Operand<vt>, ImmLeaf<vt, [{ return isInt<}] # width # [{>(Imm); }]> {
let ParserMatchClass = SHImmClass<width>;
let OperandType = "OPERAND_IMMEDIATE";
let PrintMethod = "printImm";
- let MCOperandPredicate = [{int64_t Imm; return MCOp.evaluateAsConstantImm(Imm) ? isInt<}] # width # [{>(Imm) : false;}];
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isInt<}] # width # [{>(Imm)
+ return false;
+ }];
}
-def imm8 : SHImmOp<8, i32>, ImmLeaf<i32, [{ return isInt<8>(Imm); }]>;
+def imm8 : SHImmOp<8, i32>;
// Displacement
class SHDispOp<int width, ValueType vt>
@@ -564,7 +569,7 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
def ADDI : InstRnI8<0b0111000000000000,
(outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
"add $imm,$Rn",
- [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
+ [(set i32:$Rn, (add i32:$src, imm:$imm))]>;
// addc Rm, Rn
let Defs = [SR], Uses = [SR], isCommutable = 1 in
@@ -641,54 +646,54 @@ let hasSideEffects = 0 in {
// Multiplication
//===--------------------------------------------------------------------------===//
-let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+let hasSideEffects = 0, isCommutable = 1 in {
// mac.w @Rm+, @Rn+
let Defs = [MACLO] in
def MACW : InstRmRn<0b0100000000001111,
- (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
+ (outs), (ins IGPRInc:$Rm, IGPRInc:$Rn),
"mac.w $Rm,$Rn",
[]>;
// mac.l @Rm+, @Rn+
let Defs = [MACLO, MACHI] in
def MACL : InstRmRn<0b0000000000001111,
- (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
+ (outs), (ins IGPRInc:$Rm, IGPRInc:$Rn),
"mac.l $Rm,$Rn",
[]>;
// mul.l Rm, Rn
let Defs = [MACLO] in
def MULL : InstRmRn<0b0000000000000111,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ (outs), (ins GPR:$Rm, GPR:$Rn),
"mul.l $Rm,$Rn",
[]>;
// muls.w Rm, Rn
let Defs = [MACLO] in
def MULS : InstRmRn<0b0010000000001111,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ (outs), (ins GPR:$Rm, GPR:$Rn),
"muls.w $Rm,$Rn",
[]>;
// mulu.w Rm, Rn
let Defs = [MACLO] in
def MULU : InstRmRn<0b0010000000001110,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ (outs), (ins GPR:$Rm, GPR:$Rn),
"mulu.w $Rm,$Rn",
[]>;
// dmuls.l Rm, Rn
let Defs = [MACLO, MACHI] in
def DMULS : InstRmRn<0b0011000000001101,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ (outs), (ins GPR:$Rm, GPR:$Rn),
"dmuls.l $Rm,$Rn",
[]>;
// dmulu.l Rm, Rn
let Defs = [MACLO, MACHI] in
def DMULU : InstRmRn<0b0011000000000101,
- (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+ (outs), (ins GPR:$Rm, GPR:$Rn),
"dmulu.l $Rm,$Rn",
[]>;
}
@@ -1371,9 +1376,9 @@ include "SuperHInstrDSP.td"
// def : Pat<(i32 (sextloadi8 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
// def : Pat<(i32 (sextloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
-// def : Pat<(sext_inreg i32:$src, i1), (EXTSBRmRn i32:$src)>;
-// def : Pat<(sext_inreg i32:$src, i8), (EXTSBRmRn i32:$src)>;
-// def : Pat<(sext_inreg i32:$src, i16), (EXTSWRmRn i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i1), (EXTSB i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i8), (EXTSB i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i16), (EXTSW i32:$src)>;
//===--------------------------------------------------------------------------===//
// Truncating Store
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
index 139e969eb1548..f25c7be39daf3 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -93,6 +93,39 @@ SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
);
}
+SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
+ ConstantSDNode *N,
+ SelectionDAG &DAG,
+ SHCP::SHCPModifier Modifier) {
+
+ // Early exit for null node.
+ if (!N)
+ return nullptr;
+
+ // Run though the constant pool that is tied to the DAG and search for
+ // the constant there.
+ MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+ for (auto &MC : MCP->getConstants()) {
+ if (MC.isMachineConstantPoolEntry()) {
+ if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+ if (CPV->getPromotedGlobalInit() == N->getConstantIntValue())
+ return CPV;
+ }
+ }
+ }
+
+ // If not found, create a new one and add it.
+ MachineFunction &MF = DAG.getMachineFunction();
+ SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+ unsigned LabelIndex = SFI->createConstIndex();
+ return SuperHConstantPoolConstant::Create(
+ N->getConstantIntValue(),
+ LabelIndex,
+ SHCP::SHCPKind::CPPromotedGlobal,
+ Modifier
+ );
+}
+
SuperHConstantPoolSymbol *SuperHMachineFunctionInfo::tryGetConstant(
ExternalSymbolSDNode *N,
SelectionDAG &DAG,
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
index c330e0b4ec931..db3fade2466ae 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -59,6 +59,7 @@ class SuperHMachineFunctionInfo : public MachineFunctionInfo {
// a PC-relative load.
SuperHConstantPoolConstant *tryGetConstant(GlobalAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
SuperHConstantPoolConstant *tryGetConstant(BlockAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+ SuperHConstantPoolConstant *tryGetConstant(ConstantSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
SuperHConstantPoolSymbol *tryGetConstant(ExternalSymbolSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
private:
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index c39f3d643d94f..3118603fe51d0 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -48,8 +48,6 @@ class SuperHPassConfig : public TargetPassConfig {
: TargetPassConfig(TM, PM) {}
bool addInstSelector() override;
- void addPreSched2() override;
- void addPreEmitPass() override;
void addPreEmitPass2() override;
SuperHTargetMachine &getSuperHTargetMachine() const {
return getTM<SuperHTargetMachine>();
@@ -61,14 +59,8 @@ bool SuperHPassConfig::addInstSelector() {
return false;
}
-void SuperHPassConfig::addPreSched2() {
-}
-
-void SuperHPassConfig::addPreEmitPass() {
- addPass(createSuperHFillDelaySlotsPass());
-}
-
void SuperHPassConfig::addPreEmitPass2() {
+ addPass(createSuperHFillDelaySlotsPass());
// Inserts Constant Islands. Block sizes cannot be increased after this point,
// as this may push the branch ranges and load offsets of accessing constant
>From c8469c85075c2d19572fb7ca54ea12d4b43e085e Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 6 Sep 2026 14:41:09 +0200
Subject: [PATCH 39/39] More refactoring of stack frame
---
llvm/lib/Target/SuperH/CMakeLists.txt | 1 +
.../SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 34 +-
.../SuperH/MCTargetDesc/SuperHInstPrinter.h | 9 +-
.../MCTargetDesc/SuperHMCCodeEmitter.cpp | 71 +++-
llvm/lib/Target/SuperH/README.txt | 18 +
llvm/lib/Target/SuperH/SuperH.h | 2 +
llvm/lib/Target/SuperH/SuperHCallingConv.td | 4 -
.../Target/SuperH/SuperHExpandPseudoInsts.cpp | 362 ++++++++++++++++++
.../Target/SuperH/SuperHFillDelaySlots.cpp | 9 +-
.../lib/Target/SuperH/SuperHFrameLowering.cpp | 33 +-
llvm/lib/Target/SuperH/SuperHFrameLowering.h | 1 -
llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 11 +-
llvm/lib/Target/SuperH/SuperHInstrFormats.td | 10 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 166 ++++----
llvm/lib/Target/SuperH/SuperHInstrInfo.h | 6 +-
llvm/lib/Target/SuperH/SuperHInstrInfo.td | 185 +++++----
llvm/lib/Target/SuperH/SuperHMCInstLower.cpp | 1 +
llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 155 +-------
llvm/lib/Target/SuperH/SuperHRegisterInfo.h | 1 +
.../lib/Target/SuperH/SuperHTargetMachine.cpp | 6 +
20 files changed, 717 insertions(+), 368 deletions(-)
create mode 100644 llvm/lib/Target/SuperH/README.txt
create mode 100644 llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index a09955850e10a..365ad91100316 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -32,6 +32,7 @@ add_llvm_target(SuperHCodeGen
SuperHSubtarget.cpp
SuperHFillDelaySlots.cpp
SuperHConstantIslandPass.cpp
+ SuperHExpandPseudoInsts.cpp
LINK_COMPONENTS
Analysis
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 1a6148b27ca70..1ecc1b8fbc0d9 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
@@ -45,17 +46,6 @@ void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
OS << getRegName(Reg);
}
-void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
- const MCOperand &Op0 = MI->getOperand(OpNo);
- const MCOperand &Op1 = MI->getOperand(OpNo+1);
- OS << "@(" << Op1.getImm() << "," << getRegName(Op0.getReg()) << ")";
-}
-
-void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
- const MCOperand &Op = MI->getOperand(OpNo);
- OS << Op.getImm();
-}
-
void SuperHInstPrinter::printImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo);
OS << "#" << Op.getImm();
@@ -76,7 +66,14 @@ void SuperHInstPrinter::printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostrea
OS << "@-" << getRegName(Op.getReg());
}
-void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address,
+template<int Scale>
+void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ OS << Op.getImm();
+}
+
+template<int Scale>
+void SuperHInstPrinter::printPCRel(const MCInst *MI, uint64_t Address,
unsigned OpNo, raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
@@ -94,6 +91,19 @@ void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address,
}
}
+template<int Scale>
+void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+
+ // Skip "Uses" operands, as some Memri operations are destinations.
+ if (MI->getOperand(OpNo+1).isReg())
+ OpNo++;
+
+ const MCOperand &Op0 = MI->getOperand(OpNo);
+ const MCOperand &Op1 = MI->getOperand(OpNo+1);
+
+ OS << "@(" << Op1.getImm() << "," << getRegName(Op0.getReg()) << ")";
+}
+
void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
printOperand(MI, OpNo, O);
}
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index 328c42c366b24..230b3e8cc83e6 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -51,9 +51,14 @@ class SuperHInstPrinter : public MCInstPrinter {
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
- void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
- void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ template<int Scale>
+ void printPCRel(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
+
+ template<int Scale>
void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+ template<int Scale>
+ void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 1c8a76dcc7467..848cff47c4ace 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -14,6 +14,7 @@
#include "SuperHFixupKinds.h"
#include "SuperHMCTargetDesc.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/bit.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -71,12 +72,21 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
+ const MCSubtargetInfo &STI,
+ int64_t Shift) const;
unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+
+ // Displacement
+ template<int Scale>
+ unsigned getDispOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+ // PC-relative displacement.
+ template<int Scale>
unsigned getPCRelOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -201,28 +211,73 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
++MCNumEmitted;
}
+
+
+
+//===----------------------------------------------------------------------===//
+// Branch Target
+//===----------------------------------------------------------------------===//
+
unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
}
-unsigned SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
+
+
+
+//===----------------------------------------------------------------------===//
+// Displacement
+//===----------------------------------------------------------------------===//
+
+template<int Scale>
+unsigned SuperHMCCodeEmitter::getDispOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
+ // Skip base register if found.
+ if (MI.getOperand(OpNo).isReg())
+ OpNo++;
+
+ auto MO = MI.getOperand(OpNo);
+ if (MO.isImm())
+ return (MO.getImm() / Scale);
+
+ assert(MO.isExpr() && "Expected Expression");
return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
}
-unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
+
+
+
+
+//===----------------------------------------------------------------------===//
+// PC-Relative Displacement
+//===----------------------------------------------------------------------===//
+
+template<int Scale>
+unsigned SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ auto MO = MI.getOperand(OpNo);
+ if (MO.isImm())
+ return MO.getImm() / Scale;
+
+ assert(MO.isExpr() && "Expected Expression");
+ return getExprOpValue(MI, MO.getExpr(), Fixups, STI, Scale);
+}
+
+unsigned
+SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
+ SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI,
+ int64_t Shift) const {
if (!Expr)
return 0;
switch(Expr->getKind()) {
case MCExpr::ExprKind::Binary: {
- unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI);
- Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI);
+ unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI, Shift);
+ Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI, Shift);
return Res;
}
case MCExpr::ExprKind::Target: {
@@ -259,7 +314,7 @@ unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI,
return MO.getImm();
assert(MO.isExpr() && "Expected Expression");
- return getExprOpValue(MI, MO.getExpr(), Fixups, STI);
+ return getExprOpValue(MI, MO.getExpr(), Fixups, STI, 0);
}
MCCodeEmitter *llvm::createSuperHMCCodeEmitter(const MCInstrInfo &MCII,
diff --git a/llvm/lib/Target/SuperH/README.txt b/llvm/lib/Target/SuperH/README.txt
new file mode 100644
index 0000000000000..6c34f247541fc
--- /dev/null
+++ b/llvm/lib/Target/SuperH/README.txt
@@ -0,0 +1,18 @@
+//===---------------------------------------------------------------------===//
+// Ideas for the backend.
+//===---------------------------------------------------------------------===//
+
+ * Improve SuperHFillDelaySlots pass to fill delay slots from branch
+ destinations.
+
+ * Add more variations to MOV*SFR and MOV*SFR for large stack sizes.
+ * Improve compactness of constant islands.
+
+//===---------------------------------------------------------------------===//
+// Known Issues
+//===---------------------------------------------------------------------===//
+
+ * Only SH2 level codegen is implemented.
+ * O1 compilation fails due to misgenerated fallthrough MBBs
+ * 64-bit integers are not handled.
+ * Varargs are not implemented.
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index 911234e3efefc..450191c721631 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -28,12 +28,14 @@ class SuperHTargetMachine;
FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel);
FunctionPass *createSuperHFillDelaySlotsPass();
FunctionPass *createSuperHConstantIslandPass();
+FunctionPass *createSuperHExpandPseudoPass();
void initializeSuperHDAGToDAGISelLegacyPass(PassRegistry &);
void initializeSuperHAsmPrinterPass(PassRegistry &);
void initializeSuperHAsmPrinterPass(PassRegistry &);
void initializeSuperHFillDelaySlotsPass(PassRegistry &);
void initializeSuperHConstantIslandsPass(PassRegistry &);
+void initializeSuperHExpandPseudoPass(PassRegistry &);
} // namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index 71d899d3c7e8b..20dc3f3ad42d9 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -26,10 +26,6 @@ def RetCC_SH : CallingConv<[
CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>,
CCIfType<[i64], CCAssignToReg<[R0, R1]>>,
-
- // Anything that doesn't fit in registers should be spilled.
- CCIfType<[i32], CCAssignToStack<4, 4>>,
- CCIfType<[i64], CCAssignToStack<8, 4>>,
]>;
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
new file mode 100644
index 0000000000000..5daf40e32f1d7
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -0,0 +1,362 @@
+//===-- SuperHExpandPseudoInsts.cpp - Expand pseudo instructions ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that expands pseudo instructions into target
+// instructions. This pass should be run after register allocation but before
+// the post-regalloc scheduling pass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperH.h"
+#include "SuperHInstrInfo.h"
+#include "SuperHTargetMachine.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-expand-pseudo"
+#define SH_EXPAND_PSEUDO_NAME "SH pseudo instruction expansion pass"
+
+namespace {
+class SuperHExpandPseudo : public MachineFunctionPass {
+public:
+ static char ID;
+
+ SuperHExpandPseudo() : MachineFunctionPass(ID) {}
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ StringRef getPassName() const override { return SH_EXPAND_PSEUDO_NAME; }
+
+private:
+ typedef MachineBasicBlock Block;
+ typedef Block::iterator BlockIt;
+
+ const SuperHRegisterInfo *TRI;
+ const TargetInstrInfo *TII;
+
+ bool expandMBB(Block &MBB);
+ bool expandMI(Block &MBB, BlockIt MBBI);
+ template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
+};
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Helpers
+//===----------------------------------------------------------------------===//
+
+// getOffsetForStackOffset - Calculates how much to offset the stack pointer for
+// the indirect load/store to be in range.
+static int64_t getOffsetForStackOffset(const MachineFrameInfo &MFI, int64_t StackOffset,
+ uint8_t Bits, uint8_t Scale = 1) {
+
+ // The base value range for the instruction.
+ int64_t BM = ((1<<Bits)-1)*Scale;
+ int64_t StackSize = MFI.getStackSize();
+ int64_t Slot = StackSize/BM;
+ return alignTo((BM*Slot)+(StackSize%BM), Scale);
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Frame Stores
+//===----------------------------------------------------------------------===//
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVBSFR>(Block &MBB, BlockIt MBBI) {
+ const DebugLoc &DL = MBBI->getDebugLoc();
+ MachineInstr &MI = *MBBI;
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ auto SrcReg = MI.getOperand(0).getReg();
+ auto FrameReg = MI.getOperand(1).getReg();
+ auto Offset = MI.getOperand(2).getImm();
+ int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 1);
+
+ LLVM_DEBUG(dbgs() << "Expanding MOVBSFR to MOVBS4...\n");
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov <src reg>, r0
+ // mov.b r0,@(ROff+Offset,r1)
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-SpOffset);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
+ .addReg(SrcReg);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS4))
+ .addReg(SH::R1)
+ .addImm(SpOffset-Offset);
+ MI.eraseFromParent();
+ return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVWSFR>(Block &MBB, BlockIt MBBI) {
+ const DebugLoc &DL = MBBI->getDebugLoc();
+ MachineInstr &MI = *MBBI;
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ auto SrcReg = MI.getOperand(0).getReg();
+ auto FrameReg = MI.getOperand(1).getReg();
+ auto Offset = MI.getOperand(2).getImm();
+ int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 2);
+
+ LLVM_DEBUG(dbgs() << "Expanding MOVWSFR to MOVWS4...\n");
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov <src reg>, r0
+ // mov.w r0,@(ROff+Offset,r1)
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-SpOffset);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
+ .addReg(SrcReg);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS4))
+ .addReg(SH::R1)
+ .addImm(SpOffset-Offset);
+ MI.eraseFromParent();
+ return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVLSFR>(Block &MBB, BlockIt MBBI) {
+ const DebugLoc &DL = MBBI->getDebugLoc();
+ MachineInstr &MI = *MBBI;
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ auto SrcReg = MI.getOperand(0).getReg();
+ auto FrameReg = MI.getOperand(1).getReg();
+ auto Offset = MI.getOperand(2).getImm();
+ int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 4);
+
+ LLVM_DEBUG(dbgs() << "Expanding MOVLSFR to MOVLS4...\n");
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov.l <src reg>,@(ROff+Offset,r1)
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-SpOffset);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
+ .addReg(SrcReg)
+ .addReg(SH::R1)
+ .addImm(SpOffset-Offset);
+ MI.eraseFromParent();
+ return true;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Frame Loads
+//===----------------------------------------------------------------------===//
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVBLFR>(Block &MBB, BlockIt MBBI) {
+ const DebugLoc &DL = MBBI->getDebugLoc();
+ MachineInstr &MI = *MBBI;
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ LLVM_DEBUG(dbgs() << "Expanding MOVBLFR to MOVBL4...\n");
+
+ auto DstReg = MI.getOperand(0).getReg();
+ auto FrameReg = MI.getOperand(1).getReg();
+ auto Offset = MI.getOperand(2).getImm();
+ int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 1);
+
+ // HACK: Need to find a better way of handling this, it's likely to break.
+ MBBI = std::next(MBBI);
+ MBBI = std::next(MBBI);
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov.b @(ROff+Offset,r1),r0
+ // mov r0, <dst reg>
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-SpOffset);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL4))
+ .addReg(SH::R1)
+ .addImm(SpOffset-Offset);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), DstReg)
+ .addReg(SH::R0);
+ MI.eraseFromParent();
+ return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVWLFR>(Block &MBB, BlockIt MBBI) {
+ const DebugLoc &DL = MBBI->getDebugLoc();
+ MachineInstr &MI = *MBBI;
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ LLVM_DEBUG(dbgs() << "Expanding MOVWLFR to MOVWL4...\n");
+
+ auto DstReg = MI.getOperand(0).getReg();
+ auto FrameReg = MI.getOperand(1).getReg();
+ auto Offset = MI.getOperand(2).getImm();
+ int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 2);
+
+ // HACK: Need to find a better way of handling this, it's likely to break.
+ MBBI = std::next(MBBI);
+ MBBI = std::next(MBBI);
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov.w @(ROff+Offset,r1),r0
+ // mov r0, <dst reg>
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-SpOffset);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4))
+ .addReg(SH::R1)
+ .addImm(SpOffset-Offset);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), DstReg)
+ .addReg(SH::R0);
+ MI.eraseFromParent();
+ return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVLLFR>(Block &MBB, BlockIt MBBI) {
+ const DebugLoc &DL = MBBI->getDebugLoc();
+ MachineInstr &MI = *MBBI;
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ auto DstReg = MI.getOperand(0).getReg();
+ auto FrameReg = MI.getOperand(1).getReg();
+ auto Offset = MI.getOperand(2).getImm();
+ int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 4);
+
+ LLVM_DEBUG(dbgs() << "Expanding MOVLLFR to MOVLL4...\n");
+
+ // Expand sequence to
+ // mov <base reg>,r1
+ // add #-ROff,r1
+ // mov.l @(ROff+Offset,r1),<dest reg>
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+ .addReg(FrameReg);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+ .addReg(SH::R1)
+ .addImm(-SpOffset);
+ BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4), DstReg)
+ .addReg(SH::R1)
+ .addImm(SpOffset-Offset);
+ MI.eraseFromParent();
+ return true;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// General Interface
+//===----------------------------------------------------------------------===//
+
+bool SuperHExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
+ bool Modified = false;
+
+ BlockIt MBBI = MBB.begin(), E = MBB.end();
+ while (MBBI != E) {
+ BlockIt NMBBI = std::next(MBBI);
+ Modified |= expandMI(MBB, MBBI);
+ MBBI = NMBBI;
+ }
+
+ return Modified;
+}
+
+bool SuperHExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
+ bool Modified = false;
+
+ const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+ TRI = STI.getRegisterInfo();
+ TII = STI.getInstrInfo();
+
+ for (Block &MBB : MF) {
+ bool ContinueExpanding = true;
+ unsigned ExpandCount = 0;
+
+ // Continue expanding the block until all pseudos are expanded.
+ do {
+ assert(ExpandCount < 10 && "pseudo expand limit reached");
+ (void)ExpandCount;
+
+ bool BlockModified = expandMBB(MBB);
+ Modified |= BlockModified;
+ ExpandCount++;
+
+ ContinueExpanding = BlockModified;
+ } while (ContinueExpanding);
+ }
+
+ return Modified;
+}
+
+bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
+ MachineInstr &MI = *MBBI;
+ int Opcode = MBBI->getOpcode();
+
+#define EXPAND(Op) \
+ case Op: \
+ return expand<Op>(MBB, MI)
+
+ switch(Opcode) {
+ EXPAND(SH::MOVBSFR);
+ EXPAND(SH::MOVWSFR);
+ EXPAND(SH::MOVLSFR);
+ EXPAND(SH::MOVBLFR);
+ EXPAND(SH::MOVWLFR);
+ EXPAND(SH::MOVLLFR);
+ }
+#undef EXPAND
+ return false;
+}
+
+char SuperHExpandPseudo::ID = 0;
+
+} // namespace
+
+
+INITIALIZE_PASS(SuperHExpandPseudo, "sh-expand-pseudo", SH_EXPAND_PSEUDO_NAME,
+ false, false)
+
+FunctionPass *llvm::createSuperHExpandPseudoPass() {
+ return new SuperHExpandPseudo();
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index d3f950bfb7477..5fd82e22c68bc 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -68,11 +68,18 @@ class SuperHFillDelaySlots : public MachineFunctionPass {
// for filling delay slots.
MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
+ auto *Prev = MBBI->getPrevNode();
+ // We might have a useful instruction above the instruction that
+ // loads our destination address.
+ if (MI.isCall() && Prev) {
+ if (!Prev->getPrevNode()->definesRegister(MI.getOperand(0).getReg(), TRI))
+ Prev = Prev->getPrevNode();
+ }
// TODO: Make this a while loop that keeps a list of "used" registers
// by instructions.
- if (auto *Prev = MBBI->getPrevNode()) {
+ if (Prev) {
unsigned Opcode = Prev->getOpcode();
// If we encounter a branch instruction, then it's no longer safe to
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 834422c8419c1..db3b35cb06a8d 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -17,10 +17,15 @@
#include "SuperHInstrInfo.h"
#include "SuperHRegisterInfo.h"
#include "SuperHSubtarget.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCRegister.h"
#include "llvm/Support/Debug.h"
@@ -122,35 +127,36 @@ void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, Ma
.setMIFlag(MFlag);
}
+
+
+
+//===--------------------------------------------------------------------------===//
+// Call-Frame Objects
+//===--------------------------------------------------------------------------===//
+
StackOffset
SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
Register &FrameReg) const {
const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
const MachineFrameInfo &MFI = MF.getFrameInfo();
- const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
bool HasFP = hasFP(MF);
// NOTE: All the frame indices are relative to the stack/frame pointer
// post-offset. as such an extra adjustment is needed here.
- int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
- FrameOffset += MFI.getStackSize() - TFI->getOffsetOfLocalArea();
-
- // Adjust down to remove SP.
- adjustFrameOffsetDown(FrameOffset);
+ int64_t FrameOffset = MFI.getObjectOffset(FI);
// R14 base
if (HasFP) {
// Adjust down to remove FP.
- adjustFrameOffsetDown(FrameOffset);
FrameReg = RegInfo->getFrameRegister();
- return StackOffset::getFixed(FrameOffset);
+ return StackOffset::getFixed(-FrameOffset);
}
// R15 base
FrameReg = RegInfo->getStackRegister(); // r15
- return StackOffset::getFixed(FrameOffset);
+ return StackOffset::getFixed(-FrameOffset);
}
@@ -177,11 +183,9 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
// Get stack frame size.
int64_t StackSize = MFI.getStackSize();
- adjustFrameOffsetDown(StackSize);
// Store previous frame pointer.
if (HasFP) {
- adjustFrameOffsetDown(StackSize);
BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), FP)
.addReg(SP)
.setMIFlag(MachineInstr::FrameSetup);
@@ -224,15 +228,13 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
Register FP = RII.getFrameRegister();
DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
bool HasFP = hasFP(MF);
-
+
// Get stack frame size.
int64_t StackSize = MFI.getStackSize();
- adjustFrameOffsetDown(StackSize);
// Restore stack frame
if (HasFP) {
- adjustFrameOffsetDown(StackSize);
emitFrameAdjust(FP, MF, MBB, MBBI, StackSize);
BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), SP)
.addReg(FP)
@@ -285,7 +287,7 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
const TargetInstrInfo &TII = *STI.getInstrInfo();
Register SP = RII.getStackRegister();
- for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
+ for (const CalleeSavedInfo &I : reverse(CSI)) {
MCRegister Reg = I.getReg();
BuildMI(MBB, MI, DL, TII.get(SH::MOVLM), SP)
.addReg(Reg)
@@ -344,7 +346,6 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
if (Amount == 0) {
return MBB.erase(MI);
}
-
return MBB.erase(MI);
}
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index eed0b6194cc49..10a8f8ac65b85 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -46,7 +46,6 @@ class SuperHFrameLowering : public TargetFrameLowering {
RegScavenger *RS) const override;
void emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int32_t AdjValue) const;
-
/// getFrameIndexReference - This method should return the base register
/// and offset used to reference a frame index location. The offset is
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 06e7ea01b9c7f..e1ed74ae00814 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -28,6 +28,7 @@
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetLowering.h"
@@ -67,7 +68,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setSchedulingPreference(Sched::RegPressure);
setSupportsUnalignedAtomics(false);
- setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
+ // setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
// Loads and stores are legal
for (MVT VT : MVT::integer_valuetypes()) {
@@ -122,6 +123,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
setBooleanVectorContents(ZeroOrOneBooleanContent);
setJumpIsExpensive(false);
setMinFunctionAlignment(Align(4));
+ setMinStackArgumentAlignment(Align(4));
}
//===----------------------------------------------------------------------===//
@@ -576,10 +578,7 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
// Create the CALLSEQ_END node.
Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
-
- if (!Ins.empty()) {
- InGlue = Chain.getValue(1);
- }
+ InGlue = Chain.getValue(1);
return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG, InVals);
}
@@ -601,6 +600,7 @@ SDValue SuperHTargetLowering::LowerCallResult(
for (CCValAssign const &RVLoc : RVLocs) {
Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(), InGlue)
.getValue(1);
+
InGlue = Chain.getValue(2);
InVals.push_back(Chain.getValue(0));
}
@@ -782,7 +782,6 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
-
//===----------------------------------------------------------------------===//
// SelectCC/SetCC Lowering
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index 5323f226da3a1..11ad66fe6a24a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -88,12 +88,12 @@ class SHSelectPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
class SHLoadPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
: SHPseudo<outs, ins, asmstr, pattern> {
- let usesCustomInserter = 1;
+ let mayLoad = 1;
}
class SHStorePseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
: SHPseudo<outs, ins, asmstr, pattern> {
- let usesCustomInserter = 1;
+ let mayStore = 1;
}
@@ -224,7 +224,7 @@ class InstRmRnD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pa
bits<4> disp;
let Inst{11-8} = Rn;
let Inst{7-4} = Rm;
- let Inst{0-3} = disp;
+ let Inst{3-0} = disp;
}
//===----------------------------------------------------------------------===//
@@ -242,7 +242,7 @@ class InstRnD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
bits<4> Rn;
bits<4> disp;
let Inst{7-4} = Rn;
- let Inst{0-3} = disp;
+ let Inst{3-0} = disp;
}
//===----------------------------------------------------------------------===//
@@ -260,7 +260,7 @@ class InstRmD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
bits<4> Rm;
bits<4> disp;
let Inst{7-4} = Rm;
- let Inst{0-3} = disp;
+ let Inst{3-0} = disp;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 4b56c54fd9a44..94bc9ceade1cc 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -18,6 +18,7 @@
#include "MCTargetDesc/SuperHInstPrinter.h"
#include "SuperH.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
@@ -113,6 +114,28 @@ const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
}
}
+unsigned SuperHInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
+ unsigned Opcode = MI.getOpcode();
+
+ switch (Opcode) {
+ // A regular instruction
+ default: {
+ const MCInstrDesc &Desc = get(Opcode);
+ return Desc.getSize();
+ }
+ case TargetOpcode::EH_LABEL:
+ case TargetOpcode::IMPLICIT_DEF:
+ case TargetOpcode::KILL:
+ case TargetOpcode::DBG_VALUE:
+ return 0;
+ case TargetOpcode::INLINEASM:
+ case TargetOpcode::INLINEASM_BR: {
+ // TODO: Add inline ASM support.
+ return 0;
+ }
+ }
+}
+
@@ -163,120 +186,67 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
// Stack Frames
//===----------------------------------------------------------------------===//
-void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator II,
Register SrcReg, bool isKill, int FrameIndex,
const TargetRegisterClass *RC, Register VReg,
MachineInstr::MIFlag Flags) const {
LLVM_DEBUG(dbgs() << "Store " << RI.getName(SrcReg) << " to slot " << FrameIndex << "\n");
-
- MachineFunction &MF = *MBB.getParent();
- const MachineFrameInfo &MFI = MF.getFrameInfo();
- const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
- const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
- int64_t Offset = MFI.getObjectOffset(FrameIndex) +
- MFI.getStackSize() -
- TFI->getOffsetOfLocalArea();
-
- // NOTE: R0-based displacement instructions have a different encoding
- // from Rn based instructions, as such we need to know whether
- // we need to copy the src register into R0 temporarily.
- Register SrcStrReg;
- unsigned Opcode = 0;
+
+ MachineInstr &MI = *II;
+ DebugLoc DL = MI.getDebugLoc();
if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
- Opcode = SH::MOVBS4;
- SrcStrReg = SH::R0;
+ BuildMI(MBB, II, DebugLoc(), get(SH::MOVBSFR))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addFrameIndex(FrameIndex)
+ .addImm(0)
+ .addDef(SH::R0)
+ .addUse(SH::R0);
} else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
- Opcode = SH::MOVWS4;
- SrcStrReg = SH::R0;
+ BuildMI(MBB, II, DebugLoc(), get(SH::MOVWSFR))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addFrameIndex(FrameIndex)
+ .addImm(0)
+ .addDef(SH::R0)
+ .addUse(SH::R0);
} else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
- Opcode = SH::MOVLS4;
- SrcStrReg = SrcReg;
+ BuildMI(MBB, II, DebugLoc(), get(SH::MOVLSFR))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addFrameIndex(FrameIndex)
+ .addImm(0);
} else {
- llvm_unreachable("Cannot store this register into a stack slot!");
+ llvm_unreachable("Cannot store this register into stack slot!");
}
-
- // mov r14,r1
- // add #-<frame size>,r1
- BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SH::R1)
- .addReg(SH::R14);
- BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI), SH::R1)
- .addReg(SH::R1)
- .addImm(-(int)MFI.getStackSize());
-
- // mov srcreg,r0
- // mov.b/w r0,@(<offset>,r1)
- if (SrcStrReg != SrcReg) {
- BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SrcStrReg)
- .addReg(SrcReg, getKillRegState(isKill));
- BuildMI(MBB, MI, DebugLoc(), get(Opcode))
- .addReg(SH::R1)
- .addImm(Offset);
- return;
- }
-
- // mov.l srcreg,@(<offset>,r1)
- BuildMI(MBB, MI, DebugLoc(), get(Opcode))
- .addReg(SrcReg, getKillRegState(isKill))
- .addReg(SH::R1)
- .addImm(Offset);
}
-void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator II,
Register DestReg, int FrameIndex,
const TargetRegisterClass *RC, Register VReg,
unsigned SubReg, MachineInstr::MIFlag Flags) const {
- MachineFunction &MF = *MBB.getParent();
- const SuperHRegisterInfo &RI = getRegisterInfo();
- const MachineFrameInfo &MFI = MF.getFrameInfo();
- const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
- const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
- int64_t Offset = MFI.getObjectOffset(FrameIndex) +
- MFI.getStackSize() -
- TFI->getOffsetOfLocalArea();
-
LLVM_DEBUG(dbgs() << "Load " << RI.getName(DestReg) << " from slot " << FrameIndex << "\n");
- // NOTE: R0-based displacement instructions have a different encoding
- // from Rn based instructions, as such we need to know whether
- // we need to copy to our dst register from R0.
- unsigned Opcode = 0;
- Register DstStrReg;
+ MachineInstr &MI = *II;
+ DebugLoc DL = MI.getDebugLoc();
if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
- Opcode = SH::MOVBL4;
- DstStrReg = SH::R0;
+ BuildMI(MBB, II, DebugLoc(), get(SH::MOVBLFR), DestReg)
+ .addFrameIndex(FrameIndex)
+ .addImm(0)
+ .addDef(SH::R0)
+ .addUse(SH::R0);
+
} else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
- Opcode = SH::MOVWL4;
- DstStrReg = SH::R0;
+ BuildMI(MBB, II, DebugLoc(), get(SH::MOVWLFR), DestReg)
+ .addFrameIndex(FrameIndex)
+ .addImm(0)
+ .addDef(SH::R0)
+ .addUse(SH::R0);
+
} else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
- Opcode = SH::MOVLL4;
- DstStrReg = DestReg;
+ BuildMI(MBB, II, DebugLoc(), get(SH::MOVLLFR), DestReg)
+ .addFrameIndex(FrameIndex)
+ .addImm(0);
} else {
- llvm_unreachable("Cannot load this register into a stack slot!");
- }
-
- // mov r14,r1
- // add #-<frame size>,r1
- BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SH::R1)
- .addReg(SH::R14);
- BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI), SH::R1)
- .addReg(SH::R1)
- .addImm(-(int)MFI.getStackSize());
-
- // mov.b/w @(<offset>,r1),r0
- // mov r0,dstreg
- if (DstStrReg != DestReg) {
- BuildMI(MBB, MI, DebugLoc(), get(Opcode))
- .addReg(SH::R1)
- .addImm(Offset);
- BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), DestReg)
- .addReg(DstStrReg);
- return;
+ llvm_unreachable("Cannot load this register from stack slot!");
}
-
- // mov.l @(<offset>,r1),destreg
- BuildMI(MBB, MI, DebugLoc(), get(Opcode), DestReg)
- .addReg(SH::R1)
- .addImm(Offset);
}
Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
@@ -365,7 +335,7 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
// Handle conditional branches.
ISD::CondCode BranchCode = getCondFromBranchOp(I->getOpcode());
- if (BranchCode == ISD::SETFALSE) {
+ if (BranchCode == ISD::SETCC_INVALID) {
return true; // Can't handle indirect branch.
}
@@ -524,11 +494,3 @@ bool SuperHInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
}
}
-void SuperHInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
- MachineBasicBlock &NewDestBB,
- MachineBasicBlock &RestoreBB, const DebugLoc &DL,
- int64_t BrOffset, RegScavenger *RS) const {
-
-}
-
-
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 2a73b55410f1a..78656e8b07db9 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -48,6 +48,7 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
const MCInstrDesc &getBrCond(ISD::CondCode CC) const;
// Instruction Info
+ unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
/// Return the noop instruction to use for a noop.
MCInst getNop() const override;
@@ -93,11 +94,6 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
bool isBranchOffsetInRange(unsigned BranchOpc,
int64_t BrOffset) const override;
-
- void insertIndirectBranch(MachineBasicBlock &MBB,
- MachineBasicBlock &NewDestBB,
- MachineBasicBlock &RestoreBB, const DebugLoc &DL,
- int64_t BrOffset, RegScavenger *RS) const override;
};
const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 766d6199fb376..f4fd45b1e8cd6 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -126,6 +126,18 @@ class SHRegIndirectClass<string op> : SHOpClass<"IReg" # op> {
// Operands
//===--------------------------------------------------------------------------===//
+// Operand with Scaling
+class SHScaledOp<ValueType vt, string name, int scale, bit encode = 1>
+ : Operand<vt> {
+
+ defvar Scale = !cond(!gt(scale, 0) : "<" # scale # ">", true : "");
+ defvar Suffix = Scale;
+
+ let PrintMethod = "print" # name # Suffix;
+ let EncoderMethod = !cond(encode : "get" # name # "OpValue" # Suffix, true : "");
+}
+
+
// Immediate
class SHImmOp<int width, ValueType vt>
: Operand<vt>, ImmLeaf<vt, [{ return isInt<}] # width # [{>(Imm); }]> {
@@ -139,50 +151,65 @@ class SHImmOp<int width, ValueType vt>
return false;
}];
}
+
def imm8 : SHImmOp<8, i32>;
// Displacement
-class SHDispOp<int width, ValueType vt>
- : Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
- let ParserMatchClass = SHDispClass<width>;
- let OperandType = "OPERAND_IMMEDIATE";
- let PrintMethod = "printDisp";
- let MCOperandPredicate = [{
- int64_t Imm;
- if (MCOp.evaluateAsConstantImm(Imm))
- return isUInt<#width>(Imm);
- return MCOp.isBareSymbolRef();
- }];
+class SHDispOp<int width, ValueType vt, int scale = 0>
+ : SHScaledOp<vt, "Disp", scale>,
+ PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
+ let ParserMatchClass = SHDispClass<width>;
+ let OperandType = "OPERAND_IMMEDIATE";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (MCOp.evaluateAsConstantImm(Imm))
+ return isUInt<#width>(Imm);
+ return MCOp.isBareSymbolRef();
+ }];
}
-def disp4 : SHDispOp<4, i4>;
-def disp8 : SHDispOp<8, i8>;
-def disp12 : SHDispOp<12, i16>;
-// PC-Relative Adressing
-class SHPCRelOp<int width, ValueType vt>
- : Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
- let ParserMatchClass = SHPCRelClass<>;
+// Displacement
+def disp4 : SHDispOp<4, i4, 1>;
+def disp4x2 : SHDispOp<4, i4, 2>;
+def disp4x4 : SHDispOp<4, i4, 4>;
+def disp8 : SHDispOp<8, i8, 1>;
+def disp8x2 : SHDispOp<8, i8, 2>;
+def disp8x4 : SHDispOp<8, i8, 4>;
+def disp12 : SHDispOp<12, i16, 1>;
+
+// Memory Operand
+class SHMemriOp<RegisterClass rc, Operand dt, int scale = 0>
+ : SHScaledOp<iPTR, "Memri", scale, 0>,
+ PatLeaf<(imm), [{ return isUInt<32>(N->getSExtValue()); }]> {
+ let OperandType = "OPERAND_MEMORY";
+ let MIOperandInfo = (ops rc, dt);
+}
+
+def memri : SHMemriOp<GPR, i32imm, 1>;
+def memri4 : SHMemriOp<GPR, disp4, 1>;
+def memri4x2 : SHMemriOp<GPR, disp4x2, 2>;
+def memri4x4 : SHMemriOp<GPR, disp4x4, 4>;
+def memri8x2 : SHMemriOp<GPR, disp8, 2>;
+def memri8x4 : SHMemriOp<GPR, disp8, 4>;
+
+// PCRel Operand
+class SHPCRelOp<ValueType vt, int scale = 0>
+ : SHScaledOp<vt, "PCRel", scale>,
+ PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
let OperandType = "OPERAND_PCREL";
- let EncoderMethod = "getPCRelOpValue";
- let DecoderMethod = "DecodePCRelDisp";
- let PrintMethod = "printPCRelImm";
- let MCOperandPredicate = [{
- int64_t Imm;
- if (MCOp.evaluateAsConstantImm(Imm))
- return isUInt<#width>(Imm);
- return MCOp.isBareSymbolRef();
- }];
}
-def pcrel8 : SHPCRelOp<8, i8>;
-def pcrel12 : SHPCRelOp<12, i16>;
+def pcrel8 : SHPCRelOp<i8>;
+def pcrel8x2 : SHPCRelOp<i8, 2>;
+def pcrel8x4 : SHPCRelOp<i8, 4>;
+def pcrel12 : SHPCRelOp<i16>;
// Branch Targets
def brtarget : Operand<OtherVT> {
let ParserMatchClass = SHPCRelClass<>;
let EncoderMethod = "getBranchTargetOpValue";
let DecoderMethod = "DecodeBranchTarget";
- let PrintMethod = "printPCRelImm";
+ let PrintMethod = "printPCRel<1>";
let OperandType = "OPERAND_PCREL";
}
@@ -202,14 +229,6 @@ def IGPR : SHIndirectRegOp<GPR, "">;
def IGPRInc : SHIndirectRegOp<GPR, "Inc">;
def IGPRDec : SHIndirectRegOp<GPR, "Dec">;
-// Register Indirect with Displacement @(disp,Rm)
-def memri : Operand<iPTR> {
- let MIOperandInfo = (ops GPR, disp8);
- let OperandType = "OPERAND_MEMORY";
- let EncoderMethod = "getMemriOpValue";
- let PrintMethod = "printMemri";
-}
-
// Addressing mode pattern reg+disp
let WantsRoot = true in
def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
@@ -278,23 +297,23 @@ def MOVI : InstRnI8<0b1110000000000000,
[(set i32:$Rn, imm:$imm)]>;
// mova @(disp, PC), R0
-let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
+let hasSideEffects = 0, mayLoad = 1, Uses = [PC], Defs = [R0], isDelayIllegal = 1 in
def MOVA : InstD8<0b1100011100000000,
- (outs), (ins pcrel8:$disp),
- "mova $disp,r0",
- []>;
+ (outs), (ins pcrel8x4:$disp),
+ "mova $disp,r0",
+ []>;
// mov.w @(disp,PC), Rn
-let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
+let hasSideEffects = 0, mayLoad = 1, Uses = [PC], isDelayIllegal = 1 in
def MOVWI : InstRnD8<0b1001000000000000,
- (outs GPR:$Rn), (ins pcrel8:$disp),
+ (outs GPR:$Rn), (ins pcrel8x2:$disp),
"mov.w $disp,$Rn",
[(set i32:$Rn, (sextloadi16 constpool:$disp))]>;
// mov.l @(disp,PC), Rn
-let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
+let hasSideEffects = 0, mayLoad = 1, Uses = [PC], isDelayIllegal = 1 in
def MOVLI : InstRnD8<0b1101000000000000,
- (outs GPR:$Rn), (ins pcrel8:$disp),
+ (outs GPR:$Rn), (ins pcrel8x4:$disp),
"mov.l $disp,$Rn",
[(set i32:$Rn, (load constpool:$disp))]>;
@@ -333,19 +352,19 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
def MOVBL : InstRmRn<0b0110000000000000,
(outs GPR:$Rn), (ins IGPR:$Rm),
"mov.b $Rm,$Rn",
- [(set i32:$Rn, (sextloadi8 IGPR:$Rm))]>;
+ []>;
// mov.w @Rm, Rn
def MOVWL : InstRmRn<0b0110000000000001,
(outs GPR:$Rn), (ins IGPR:$Rm),
"mov.w $Rm,$Rn",
- [(set i32:$Rn, (sextloadi16 IGPR:$Rm))]>;
+ []>;
// mov.l @Rm, Rn
def MOVLL : InstRmRn<0b0110000000000010,
(outs GPR:$Rn), (ins IGPR:$Rm),
"mov.l $Rm,$Rn",
- [(set i32:$Rn, (load IGPR:$Rm))]>;
+ []>;
// mov.b @Rm+, Rn
let isDelayIllegal = 1 in
@@ -371,22 +390,22 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
// mov.b @(disp, Rm), R0
let Defs = [R0] in
def MOVBL4 : InstRmD4<0b1000010000000000,
- (outs), (ins (memri $Rm, $disp):$src),
+ (outs), (ins (memri4 $Rm, $disp):$src),
"mov.b $src,R0",
- [(set R0, (sextloadi8 addr:$src))]>;
+ []>;
// mov.w @(disp, Rm), R0
let Defs = [R0] in
def MOVWL4 : InstRmD4<0b1000010100000000,
- (outs), (ins (memri $Rm, $disp):$src),
+ (outs), (ins (memri4x2 $Rm, $disp):$src),
"mov.w $src,R0",
- [(set R0, (sextloadi16 addr:$src))]>;
+ []>;
// mov.l @(disp, Rm), Rn
def MOVLL4 : InstRmRnD4<0b0101000000000000,
- (outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+ (outs GPR:$Rn), (ins (memri4x4 $Rm, $disp):$src),
"mov.l $src,$Rn",
- [(set i32:$Rn, (load addr:$src))]>;
+ []>;
// mov.b @(R0,Rm),Rn
let Uses = [R0] in
@@ -444,19 +463,19 @@ let hasSideEffects = 0, mayStore = 1 in {
def MOVBS : InstRmRn<0b0010000000000000,
(outs), (ins GPR:$Rm, IGPR:$Rn),
"mov.b $Rm,$Rn",
- [(truncstorei8 i32:$Rm, i32:$Rn)]>;
+ []>;
// mov.w Rm, @Rn
def MOVWS : InstRmRn<0b0010000000000001,
(outs), (ins GPR:$Rm, IGPR:$Rn),
"mov.w $Rm,$Rn",
- [(truncstorei16 i32:$Rm, i32:$Rn)]>;
+ []>;
// mov.l Rm, @Rn
def MOVLS : InstRmRn<0b0010000000000010,
(outs), (ins GPR:$Rm, IGPR:$Rn),
"mov.l $Rm,$Rn",
- [/*(store i32:$Rm, i32:$Rn)*/]>;
+ []>;
// mov.b Rm, @-Rn
let isDelayIllegal = 1 in
@@ -482,22 +501,22 @@ let hasSideEffects = 0, mayStore = 1 in {
// mov.b R0, @(disp, Rn)
let Uses = [R0] in
def MOVBS4 : InstRnD4<0b1000000000000000,
- (outs), (ins (memri $Rn, $disp):$dst),
+ (outs), (ins (memri4 $Rn, $disp):$dst),
"mov.b r0,$dst",
- [/*(truncstorei8 i32, addr:$dst)*/]>;
+ []>;
// mov.w R0, @(disp, Rn)
let Uses = [R0] in
def MOVWS4 : InstRnD4<0b1000000100000000,
- (outs), (ins (memri $Rn, $disp):$dst),
+ (outs), (ins (memri4x2 $Rn, $disp):$dst),
"mov.w r0,$dst",
- [/*(truncstorei16 i32, addr:$dst)*/]>;
+ []>;
// mov.l Rm, @(disp, Rn)
def MOVLS4 : InstRmRnD4<0b0001000000000000,
- (outs), (ins GPR:$Rm, (memri $Rn, $disp):$dst),
+ (outs), (ins GPR:$Rm, (memri4x4 $Rn, $disp):$dst),
"mov.l $Rm,$dst",
- [(store i32:$Rm, addr:$dst)]>;
+ []>;
// mov.b Rm,@(R0,Rn)
let Uses = [R0] in
@@ -1380,14 +1399,6 @@ def : Pat<(sext_inreg i32:$src, i1), (EXTSB i32:$src)>;
def : Pat<(sext_inreg i32:$src, i8), (EXTSB i32:$src)>;
def : Pat<(sext_inreg i32:$src, i16), (EXTSW i32:$src)>;
-//===--------------------------------------------------------------------------===//
-// Truncating Store
-//===--------------------------------------------------------------------------===//
-
-// def : Pat<(truncstorei8 i32:$src, i32:$dst), (MOVBRmRni i32:$src, i32:$dst)>;
-// def : Pat<(truncstorei16 i32:$src, i32:$dst), (MOVWRmRni i32:$src, i32:$dst)>;
-
-
//===--------------------------------------------------------------------------===//
//===--------------------------------------------------------------------------===//
@@ -1417,6 +1428,36 @@ def Select32 : SHSelectPseudo<(outs GPR:$dst),
[(set i32:$dst,
(SHselectcc i32:$src, i32:$src2, imm:$cc))]>;
+//===--------------------------------------------------------------------------===//
+// Frame Load/Store
+//===--------------------------------------------------------------------------===//
+
+// LOAD FROM FRAME
+def MOVBLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+ "! MOVBLFR $src, $Rn",
+ [(set i32:$Rn, (extloadi8 addr:$src))]>;
+
+def MOVWLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+ "! MOVWLFR $src, $Rn",
+ [(set i32:$Rn, (extloadi16 addr:$src))]>;
+
+def MOVLLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+ "! MOVLLFR $src, $Rn",
+ [(set i32:$Rn, (load addr:$src))]>;
+
+// STORE TO FRAME
+def MOVBSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+ "! MOVBSFR $src, $dst",
+ [(truncstorei8 i32:$src, addr:$dst)]>;
+
+def MOVWSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+ "! MOVWSFR $src, $dst",
+ [(truncstorei16 i32:$src, addr:$dst)]>;
+
+def MOVLSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+ "! MOVLSFR $src, $dst",
+ [(store i32:$src, addr:$dst)]>;
+
//===--------------------------------------------------------------------------===//
// Stack Frame
//===--------------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index 79451cd815e4a..d64518bac837f 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -65,6 +65,7 @@ void SuperHMCInstLower::lowerInstruction(const MachineInstr &MI,
// Ignore all implicit register operands.
if (MO.isImplicit())
continue;
+
MCOp = MCOperand::createReg(MO.getReg());
break;
case MachineOperand::MO_Immediate:
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 86867e04273b2..a1ed734beedb1 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -23,6 +23,9 @@
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include <cstdint>
using namespace llvm;
@@ -71,61 +74,26 @@ SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
+ const SuperHFrameLowering *FR = getFrameLowering(MF);
// R0 is always reserved as some instructions can only write to it.
Reserved.set(SH::R0);
-
- // Reserve GOT pointer
- Reserved.set(SH::R12);
- // Also reserve the stack frame and stack pointer.
- Reserved.set(SH::R14);
+ // R1 is generally used as the temporary storage for addresses.
+ Reserved.set(SH::R1);
+
+ // Also reserve the stack pointer.
Reserved.set(SH::R15);
- // Status Register
- Reserved.set(SH::SR);
- return Reserved;
-}
-
-/// getLoadBaseOffset - Gets the base offset to emit a load/store from.
-static int64_t getLoadStoreBaseOffset(unsigned Opcode) {
- switch(Opcode) {
- case SH::MOVBL4:
- case SH::MOVBS4:
- return 12;
-
- case SH::MOVWL4:
- case SH::MOVWS4:
- return 28;
-
- case SH::MOVLS4:
- case SH::MOVLL4:
- return 60;
-
- default:
- return 0;
- }
-}
-
-/// getLoadBaseOffset - Gets the neccesary bit shift amount for the
-/// load/store indexing
-static int64_t getLoadStoreOffsetShift(unsigned Opcode) {
- switch(Opcode) {
- case SH::MOVBL4:
- case SH::MOVBS4:
- return 0;
-
- case SH::MOVWL4:
- case SH::MOVWS4:
- return 1;
+ // Reserve GOT pointer
+ if (Subtarget.isPositionIndependent())
+ Reserved.set(SH::R12);
- case SH::MOVLS4:
- case SH::MOVLL4:
- return 2;
+ // Reserver frame pointer if it's used.
+ if (FR->hasFP(MF))
+ Reserved.set(SH::R14);
- default:
- return 0;
- }
+ return Reserved;
}
static void replaceFI(const MachineFunction &MF, MachineBasicBlock::iterator II,
@@ -153,94 +121,13 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
// Get the register offset to fetch.
Register FrameReg;
int64_t Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
- int64_t ROff = getLoadStoreBaseOffset(MI.getOpcode());
- int64_t Shift = getLoadStoreOffsetShift(MI.getOpcode());
-
- // Handle frame loads and stores.
- switch(MI.getOpcode()) {
-
- // Stack Store
- case SH::MOVBS4:
- case SH::MOVWS4: {
- Register SrcReg = MI.getOperand(0).getReg();
-
- // Expand sequence to
- // mov <base reg>,r1
- // add #-ROff,r1
- // mov <src reg>, r0
- // mov.w/b r0,@(ROff+Offset,r1)
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
- .addReg(FrameReg);
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
- .addReg(SH::R1)
- .addImm(-ROff);
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R0)
- .addReg(SrcReg);
-
- Offset = (ROff-Offset) >> Shift;
- FrameReg = SH::R1;
- break;
- }
- case SH::MOVLS4: {
-
- // Expand sequence to
- // mov <base reg>,r1
- // add #-ROff,r1
- // mov.l <src reg>,@(ROff+Offset,r1)
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
- .addReg(FrameReg);
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
- .addReg(SH::R1)
- .addImm(-ROff);
-
- Offset = (ROff-Offset) >> Shift;
- FrameReg = SH::R1;
- break;
- }
-
- // Stack Load
- case SH::MOVBL4:
- case SH::MOVWL4: {
- Register DstReg = MI.getOperand(0).getReg();
-
- // Expand sequence to
- // mov <base reg>,r1
- // add #-ROff,r1
- // mov.w/b @(ROff+Offset,r1),r0
- // mov r0,<dst reg>
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
- .addReg(FrameReg);
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
- .addReg(SH::R1)
- .addImm(-ROff);
-
- // This inserts it after our instruction
- BuildMI(*MI.getParent(), MI, DL, TII.get(SH::ADDI), DstReg)
- .addReg(SH::R0)
- .addImm(-ROff);
-
- Offset = (ROff-Offset) >> Shift;
- FrameReg = SH::R1;
- break;
- }
- case SH::MOVLL4: {
-
- // Expand sequence to
- // mov <base reg>,r1
- // add #-ROff,r1
- // mov.l @(ROff+Offset,r1),<dst reg>
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
- .addReg(FrameReg);
- BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
- .addReg(SH::R1)
- .addImm(-ROff);
-
- Offset = (ROff-Offset) >> Shift;
- FrameReg = SH::R1;
- break;
- }
- }
+ LLVM_DEBUG({
+ int64_t Fo = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
+ dbgs() << "Eliminiate FI " << FrameIndex << " @ SP["
+ << -Fo << "]...\n";
+ });
+
replaceFI(MF, II, MI, DL, FIOperandNum, Offset, FrameReg);
return false;
}
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index 0a69b4b9a8c2c..1c7c1f52fea51 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -36,6 +36,7 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
const TargetRegisterClass *getLargestLegalSuperClass(const TargetRegisterClass *RC,
const MachineFunction &MF) const override;
Register getFrameRegister(const MachineFunction &MF) const override;
+
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 3118603fe51d0..18dd3cfc1e7e0 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -32,6 +32,7 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSuperHTarget() {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeSuperHAsmPrinterPass(Registry);
+ initializeSuperHExpandPseudoPass(Registry);
initializeSuperHFillDelaySlotsPass(Registry);
initializeSuperHConstantIslandsPass(Registry);
initializeSuperHDAGToDAGISelLegacyPass(Registry);
@@ -48,6 +49,7 @@ class SuperHPassConfig : public TargetPassConfig {
: TargetPassConfig(TM, PM) {}
bool addInstSelector() override;
+ void addPreSched2() override;
void addPreEmitPass2() override;
SuperHTargetMachine &getSuperHTargetMachine() const {
return getTM<SuperHTargetMachine>();
@@ -59,7 +61,11 @@ bool SuperHPassConfig::addInstSelector() {
return false;
}
+void SuperHPassConfig::addPreSched2() {
+}
+
void SuperHPassConfig::addPreEmitPass2() {
+ addPass(createSuperHExpandPseudoPass());
addPass(createSuperHFillDelaySlotsPass());
// Inserts Constant Islands. Block sizes cannot be increased after this point,
More information about the cfe-commits
mailing list