[clang] [llvm] Add SuperH (1-4a) target (PR #181287)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 8 06:51:11 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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";
More information about the llvm-commits
mailing list