[clang] [compiler-rt] [llvm] Add SuperH (1-4a) target (PR #181287)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 00:27:51 PDT 2026


https://github.com/LunaTheFoxgirl updated https://github.com/llvm/llvm-project/pull/181287

>From 103a4cf45822aefe994738028594c2249569d548 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/67] 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 825dbce14d67c..4fd3c2ac19db0 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -632,6 +632,7 @@ set(LLVM_ALL_EXPERIMENTAL_TARGETS
   CSKY
   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 9dacae1a8eb290cbf97d2f82de37bc815cd638f3 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/67] 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 45256bde744de..6058243b57bad 100644
--- a/llvm/Maintainers.md
+++ b/llvm/Maintainers.md
@@ -387,6 +387,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 efef8f12a0930c2efc0d1d5d3581582545b8dcfe 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/67] 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 b369b66960b1a..f1ca3fbe77b5b 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -80,6 +80,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 ceabfe403e9c3..63d1601e206a6 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -119,6 +119,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
     return "riscv32be";
   case riscv64be:
     return "riscv64be";
+  case sh:
+    return "sh";
   case shave:
     return "shave";
   case sparc:
@@ -995,6 +997,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:
@@ -1761,6 +1764,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:
@@ -1872,6 +1876,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:
@@ -1964,6 +1969,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 bd2737b42099b59118954f3387abb1221241aebe 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/67] 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 f1ca3fbe77b5b..452cfef51a1a8 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -80,7 +80,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 c4de5d50bb8e3..795136c950c20 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -564,6 +564,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:
@@ -623,6 +648,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 63d1601e206a6..161df3949d756 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -121,6 +121,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
     return "riscv64be";
   case sh:
     return "sh";
+  case sh_le:
+    return "sh_le";
   case shave:
     return "shave";
   case sparc:
@@ -998,6 +1000,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:
@@ -1765,6 +1768,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:
@@ -1877,6 +1881,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:
@@ -1970,6 +1975,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:
@@ -2150,6 +2156,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;
@@ -2205,6 +2214,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;
@@ -2245,6 +2257,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 00b3573224a44a33a70b066f7dd01a08d6cb73eb 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/67] 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 6bb387799c4a1..f6fac5d28ad6b 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 119aea1e09862cfebd3647872c37500f9b180cf0 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/67] 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 c97846fa9203d5f6a1f871e5358c5513e75f8585 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/67] 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 161df3949d756..00a9d53596ec1 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -491,6 +491,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)
@@ -646,6 +648,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 dab2f4cb31dc7b7a3c7b0f19afafb9114d91e062 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/67] 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 d0a301ab233bc269a139534cdd16fcb0d2c3642d 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/67] 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 a18d63ff6e3a1ce698f3ac4caea9b67deee5a32f 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/67] 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 c1b7198565f07..5e0a6c44c318c 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -312,6 +312,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 f6fac5d28ad6b..48f25d02cb80e 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 1a46cac48808c0ad04063b81143b2e0409bec49d 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/67] 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 b6413ee924a377562e8d279232f41fb2c2c5320b 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/67] 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 51ae149406e7f3b9cc8b5c458eb37de70d821d98 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/67] 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 e80d789b8e193d6572d5ba3a64709810b15dee0b 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/67] 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 f8adec9518e624c8c029db262c93d764ee5e4d2a 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/67] 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 6329c3fa8b34e..94c19bf120a1a 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 8c01cfca8ccb4..d65774fc08c3b 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 452cfef51a1a8..235b691789720 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -1192,6 +1192,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 795136c950c20..ca8ebf1cef240 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -575,8 +575,15 @@ static std::string computeSuperHDataLayout(const Triple &T) {
   // 32-bit pointers, 32 bit aligned
   Ret += "-p:32:32";
 
-  // 32 bit integers, 32 bit aligned
+  // Integer alignments
+  Ret += "-i18:32";
+  Ret += "-i16:32";
   Ret += "-i32:32";
+  Ret += "-i64:64";
+
+  // Floating alignments
+  Ret += "-f32:32";
+  Ret += "-f64:64";
 
   // 32 bit alignment of objects of aggregate type
   Ret += "-a:0:32";

>From 84d8d01006db0566c5a992cd526688a4946621a1 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 9 Aug 2026 05:20:38 +0200
Subject: [PATCH 16/67] Add more instructions, expand sdiv and udiv

---
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |   3 +-
 llvm/lib/Target/SuperH/SuperH.td              |  39 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  25 +-
 llvm/lib/Target/SuperH/SuperHInstrFormats.td  |  16 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  65 ++
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |   5 +
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 559 +++++++++++++++---
 7 files changed, 604 insertions(+), 108 deletions(-)

diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 95d0618ad6478..3ddbb766796f1 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -50,8 +50,7 @@ void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostrea
 
 	// Print immediates
 	if (Op.isImm()) {
-		assert(Op.getImm() <= 255 && "Only 8-bit immediates are supported.");
-		O << "#" << Op.getImm();
+		O << Op.getImm();
 		return;
 	}
 }
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index fad2c4fb6f106..03809c4d7a31d 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -23,14 +23,17 @@ include "llvm/TableGen/SearchableTable.td"
 
 // NOTE:  Some SH4 CPUs support FSCA and FSRRA despite their
 //        ISA manuals not specifying so.
+def FeatureFPU      : SubtargetFeature<"fp32", "HasFPU", "true",
+                                       "Enable use of 32-bit floating point instructions.">;
+def FeatureFPU64    : SubtargetFeature<"fp64", "HasFP64", "true",
+                                       "Enable use of 64-bit floating point instructions.",
+                                       [FeatureFPU]>;
 def FeatureFSCA     : SubtargetFeature<"fsca", "HasFSCA", "true",
-                                       "Enable use of fsca instruction.">;
+                                       "Enable use of fsca instruction.",
+                                       [FeatureFPU]>;
 def FeatureFSRRA    : SubtargetFeature<"fsrra", "HasFSRRA", "true",
-                                       "Enable use of fsrra instruction.">;
-def FeatureFP32     : SubtargetFeature<"fp32", "HasFP32", "true",
-                                       "Enable use of 32-bit floating point instructions.">;
-def FeatureFP64     : SubtargetFeature<"fp64", "HasFP64", "true",
-                                       "Enable use of 64-bit floating point instructions.">;
+                                       "Enable use of fsrra instruction.",
+                                       [FeatureFPU]>;
 def FeatureDSP      : SubtargetFeature<"dsp", "HasDSP", "true",
                                        "Enable SuperH DSP Extensions">;
 
@@ -38,31 +41,29 @@ def FeatureDSP      : SubtargetFeature<"dsp", "HasDSP", "true",
 // SuperH CPU Family features
 //===----------------------------------------------------------------------===//
 
-def FeatureSH1      : SubtargetFeature<"sh1", "SHArchVersion", "SH1",
-                          "SH-1 ISA Support">;
 def FeatureSH2      : SubtargetFeature<"sh2", "SHArchVersion", "SH2",
                           "SH-2 ISA Support",
-                          [FeatureSH1]>;
+                          []>;
 def FeatureSH2E     : SubtargetFeature<"sh2e", "SHArchVersion", "SH2E",
                           "SH-2E ISA Support",
-                          [FeatureSH1, FeatureSH2, FeatureFP32]>;
+                          [FeatureSH2, FeatureFPU]>;
 def FeatureSH2A     : SubtargetFeature<"sh2a", "SHArchVersion", "SH2A",
                           "SH-2A ISA Support",
-                          [FeatureSH1, FeatureSH2, FeatureFP32, FeatureFP64]>;
+                          [FeatureSH2, FeatureFPU, FeatureFPU64]>;
 def FeatureSH3      : SubtargetFeature<"sh3", "SHArchVersion", "SH3",
                           "SH-3 ISA Support",
-                          [FeatureSH1, FeatureSH2]>;
+                          [FeatureSH2]>;
 def FeatureSH3E     : SubtargetFeature<"sh3e", "SHArchVersion", "SH3E",
                           "SH-3E ISA Support",
-                          [FeatureSH1, FeatureSH2, FeatureFP32]>;
+                          [FeatureSH2, FeatureFPU]>;
 def FeatureSH4      : SubtargetFeature<"sh4", "SHArchVersion", "SH4",
                           "SH-4 ISA Support",
-                          [FeatureSH1, FeatureSH2, FeatureSH3, FeatureFP32, 
-                           FeatureFP64]>;
+                          [FeatureSH2, FeatureSH3, FeatureFPU, 
+                           FeatureFPU64]>;
 def FeatureSH4A     : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
                           "SH-4A ISA Support",
-                          [FeatureSH1, FeatureSH2, FeatureSH3, FeatureSH4, 
-                           FeatureFP32, FeatureFP64, FeatureFSCA, FeatureFSRRA]>;
+                          [FeatureSH2, FeatureSH3, FeatureSH4, 
+                           FeatureFPU, FeatureFPU64, FeatureFSCA, FeatureFSRRA]>;
 
 //===----------------------------------------------------------------------===//
 // SuperH Processors
@@ -73,8 +74,8 @@ include "SuperHSchedule.td"
 class ProcModel<string Name, list<SubtargetFeature> Features>
     : ProcessorModel<Name, GenericSuperHModel, Features>;
 
-def : ProcModel<"generic", [FeatureSH4]>;
-def : ProcModel<"sh1", [FeatureSH1]>;
+def : ProcModel<"generic", [FeatureSH2]>;
+def : ProcModel<"sh1", []>;
 def : ProcModel<"sh2", [FeatureSH2]>;
 def : ProcModel<"sh2e", [FeatureSH2E]>;
 def : ProcModel<"sh2a", [FeatureSH2A]>;
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 645e2884e269f..d14e187479bb3 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -19,6 +19,7 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/DebugLog.h"
 
 #define DEBUG_TYPE "sh-isel"
 #define PASS_NAME "SH DAG->DAG Instruction Selection"
@@ -39,15 +40,19 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
   bool SelectInlineAsmMemoryOperand(const SDValue &Op,
                                     InlineAsm::ConstraintCode ConstraintCode,
                                     std::vector<SDValue> &OutOps) override;
-  bool trySelectRET(SDNode *N);
-  bool trySelectFrameIndex(SDNode *N);
+  bool SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValue Rhs);
 
 // Include the pieces autogenerated from the target description.
 #include "SuperHGenDAGISel.inc"
 
 private:
   void Select(SDNode *N) override;
+
   bool trySelect(SDNode *N);
+  bool trySelectRET(SDNode *N);
+  bool trySelectSDIV(SDNode *N);
+  bool trySelectUDIV(SDNode *N);
+  bool trySelectFrameIndex(SDNode *N);
 
   const SuperHSubtarget *Subtarget;
 };
@@ -75,6 +80,22 @@ bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
   return false;
 }
 
+
+//===----------------------------------------------------------------------===//
+//                              Address Lowering
+//===----------------------------------------------------------------------===//
+
+bool SuperHDAGToDAGISel::SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValue Rhs) {
+  return false;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                             Branch Lowering
+//===----------------------------------------------------------------------===//
+
 // Due to delay slots there needs to be a bit more smarts
 // in here.
 bool SuperHDAGToDAGISel::trySelectRET(SDNode *N) {
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index 442a543807aa3..df62cf6e9cfc4 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -152,7 +152,7 @@ class InstRm<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patter
 // Immediate -> Register Instruction
 // <opop|rnrn|iiiiiiii>
 //===----------------------------------------------------------------------===//
-class InstI8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
+class InstRnI8<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
     : SHInst16<outs, ins, asmstr, pattern> {
 
   // Opcode
@@ -170,7 +170,7 @@ class InstI8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
 // (disp:8) -> Register Instruction
 // <opop|rnrn|dddddddd>
 //===----------------------------------------------------------------------===//
-class InstD8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
+class InstRnD8<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
     : SHInst16<outs, ins, asmstr, pattern> {
   
   
@@ -189,7 +189,7 @@ class InstD8Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
 // (Register + disp:4) -> Register Instruction
 // <opop|rnrn|rmrm|dddd>
 //===----------------------------------------------------------------------===//
-class InstRmD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
+class InstRmRnD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
     : SHInst16<outs, ins, asmstr, pattern> {
   
   // Opcode
@@ -209,7 +209,7 @@ class InstRmD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pa
 // (disp:4) -> Register Instruction
 // <opopopop|rnrn|dddd>
 //===----------------------------------------------------------------------===//
-class InstD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
+class InstRnD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
     : SHInst16<outs, ins, asmstr, pattern> {
   
   // Opcode
@@ -227,7 +227,7 @@ class InstD4Rn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
 // (disp:4 + Register) -> Reserved Register Instruction
 // <opopopop|rmrm|dddd>
 //===----------------------------------------------------------------------===//
-class InstD4RmRr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
+class InstRmD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
     : SHInst16<outs, ins, asmstr, pattern> {
   
   // Opcode
@@ -245,7 +245,7 @@ class InstD4RmRr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> p
 // (disp:8) Instruction
 // <opopopop|dddddddd>
 //===----------------------------------------------------------------------===//
-class InstD8Rr<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
+class InstD8<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
     : SHInst16<outs, ins, asmstr, pattern> {
   
   // Opcode
@@ -261,7 +261,7 @@ class InstD8Rr<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
 // (imm:8) Instruction
 // <opopopop|iiiiiiii>
 //===----------------------------------------------------------------------===//
-class InstI8Rr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
+class InstI8<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
     : SHInst16<outs, ins, asmstr, pattern> {
   
   // Opcode
@@ -277,7 +277,7 @@ class InstI8Rr <bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pat
 // (disp:12) Instruction
 // <opop|dddddddddddd>
 //===----------------------------------------------------------------------===//
-class InstD12Rr<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
+class InstD12<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pattern = []> 
     : SHInst16<outs, ins, asmstr, pattern> {
   
   // Opcode
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 303048a47389a..9b76cd1d4a9b6 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -17,6 +17,8 @@
 #include "SuperHTargetMachine.h"
 #include "SuperH.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -48,4 +50,67 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 
   // Otherwise this is not possible.
   llvm_unreachable("Impossible reg-to-reg copy");
+}
+
+bool SuperHInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
+  unsigned OpCode = MI.getOpcode();
+  switch(OpCode) {
+  case SH::DIVURmRn:
+  case SH::DIVSRmRn:
+    return expandDIV(OpCode, MI);
+  default:
+    return false;
+  }
+}
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                        Pseudo Instruction Expansion
+//===----------------------------------------------------------------------===//
+
+// Expands the division psuedo instructions into valid SuperH sequences.
+// SuperH sets the division mode with an struction inserted before.
+bool SuperHInstrInfo::expandDIV(unsigned Opcode, MachineInstr &MI) const {
+  assert(MI.getOperand(0).isReg() && "Expected register in op0 for expansion!");
+  assert(MI.getOperand(1).isReg() && "Expected register in op1 for expansion!");
+  auto &MBB = *MI.getParent();
+  auto Lhs = MI.getOperand(0).getReg();
+  auto Rhs = MI.getOperand(1).getReg();
+  auto DL = MI.getDebugLoc();
+
+  switch(Opcode) {
+
+  // Expand DIVURmRn to the following sequence:
+  // div0u
+  // div1 Rm, Rn
+  case SH::DIVURmRn: {
+    BuildMI(MBB, MI, DL, get(SH::DIV0U));
+    BuildMI(MBB, MI, DL, get(SH::DIV1RmRn), Rhs)
+      .addReg(Lhs);
+    MI.removeFromParent();
+    return true;
+  }
+
+  // Expand DIVSRmRn to the following sequence:
+  // div0s Rm, Rn
+  // div1 Rm, Rn
+  case SH::DIVSRmRn: {
+    BuildMI(MBB, MI, DL, get(SH::DIV0SRmRn))
+      .addReg(Rhs)
+      .addReg(Lhs);
+    BuildMI(MBB, MI, DL, get(SH::DIV1RmRn), Rhs)
+      .addReg(Lhs);
+    MI.removeFromParent();
+    return true;
+  }
+
+  // This shouldn't be reached.
+  default: {
+    llvm_unreachable("expandDIV was wrongfully called on a non-div pseudo!");
+    return false; 
+  }
+  }
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 65231455267a9..ae47b75d7ffc0 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -40,6 +40,11 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
                            Register DestReg, Register SrcReg, bool KillSrc,
                            bool RenamableDest = false,
                            bool RenamableSrc = false) const override;
+
+  bool expandPostRAPseudo(MachineInstr &MI) const override;
+
+private:
+  bool expandDIV(unsigned Opcode, MachineInstr &MI) const;
 };
 
 const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 8bd12bd5cfcbb..4a8414f16f11a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -4,29 +4,33 @@
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 ///
 /// \file
 /// This file describes the SuperH instruction set, defining the instructions
 /// and properties of the instructions which are needed for code generation,
 /// machine code emission, and analysis.
 ///
+/// The instructions in this file in particular cover SH1-2.
+/// later version and extensions are in their respective files.
+///
 /// The subsystems are ordered after the instruction classification that
 /// The SuperH ISA manuals use.
 ///
 /// See: https://www.shared-ptr.com/sh_insns.html
+/// See: https://saturnopensdk.github.io/
 ///
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // Instruction Formats
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 include "SuperHInstrFormats.td"
 
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // Instruction Patterns
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 defvar SH = DefaultMode;
 def sh_ptr_rc : RegClassByHwMode<[SH], [GPR]>;
@@ -37,18 +41,17 @@ def ptr_op : RegisterOperand<sh_ptr_rc> {
   let DecoderMethod = "DecodeIntRegsRegisterClass";
 }
 
-
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // SuperH Type Profiles
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 def SHSDT_CallSeqStart  : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
 def SHSDT_CallSeqEnd  : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
 def SHSDT_Call        : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
 
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // SuperH Specific Nodes
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 def SHCallSeqStart  : SDNode<"ISD::CALLSEQ_START", SHSDT_CallSeqStart,
                             [SDNPHasChain, SDNPOutGlue]>;
@@ -64,9 +67,9 @@ def SHRet           : SDNode<"SHISD::RET", SDTNone,
                             [SDNPHasChain, SDNPOptInGlue, 
                              SDNPVariadic]>;
 
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // Operand Classes
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 // Base Operand Class
 class SHOpClass<string name, 
@@ -94,9 +97,9 @@ def SHMemClass : SHOpClass<"Mem"> {
   let RenderMethod = "addMemOperands";
 }
 
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // Operands
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 // Immediate
 class SHImmOp<int width, ValueType vt>
@@ -165,22 +168,51 @@ def MemR0I : Operand<iPTR> {
 let WantsRoot = true in
 def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
 
+//===--------------------------------------------------------------------------===//
+// Predicates
+//===--------------------------------------------------------------------------===//
+
+def HasFSCA     : Predicate<"Subtarget->hasFSCA()">,
+                  AssemblerPredicate<(all_of FeatureFSCA)>;
+
+def HasFSRRA    : Predicate<"Subtarget->hasFSRRA()">,
+                  AssemblerPredicate<(all_of FeatureFSRRA)>;
+
+def HasFPU      : Predicate<"Subtarget->hasFPU()">,
+                  AssemblerPredicate<(all_of FeatureFPU)>;
+
+def HasDSP      : Predicate<"Subtarget->hasDSP()">,
+                  AssemblerPredicate<(all_of FeatureDSP)>;
 
+def HasSH2      : Predicate<"Subtarget->hasSH2Inst()">,
+                  AssemblerPredicate<(all_of FeatureSH2)>;
 
+def HasSH2E     : Predicate<"Subtarget->hasSH2EInst()">,
+                  AssemblerPredicate<(all_of FeatureSH2E)>;
 
+def HasSH2A     : Predicate<"Subtarget->hasSH2AInst()">,
+                  AssemblerPredicate<(all_of FeatureSH2A)>;
 
-//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-// Instruction Definitions
-//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
+def HasSH3      : Predicate<"Subtarget->hasSH3Inst()">,
+                  AssemblerPredicate<(all_of FeatureSH3)>;
 
+def HasSH3E     : Predicate<"Subtarget->hasSH3EInst()">,
+                  AssemblerPredicate<(all_of FeatureSH3E)>;
 
+def HasSH4      : Predicate<"Subtarget->hasSH4Inst()">,
+                  AssemblerPredicate<(all_of FeatureSH4)>;
 
+def HasSH4A     : Predicate<"Subtarget->hasSH4AInst()">,
+                  AssemblerPredicate<(all_of FeatureSH4A)>;
 
-//===----------------------------------------------------------------------===//
-// Data Transfer Instructions
-//===----------------------------------------------------------------------===//
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                          Data Transfer Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 // mov Rm, Rn
 let hasSideEffects = 0 in
@@ -191,77 +223,286 @@ def MOVRmRn       : InstRmRn<0b0110000000000011,
 
 // mov #imm:8, Rn
 let hasSideEffects = 0 in 
-def MOVI8Rn       : InstI8Rn<0b1110000000000000,
+def MOVI8Rn       : InstRnI8<0b1110000000000000,
                             (outs GPR:$Rn), (ins imm8:$imm),
                             "mov #$imm,$Rn",
                             [(set i32:$Rn, imm8:$imm)]>;
 
+// mov @(disp, PC), R0
+let hasSideEffects = 0, mayLoad = 1, Defs = [R0] in
+def MOVAD8PCR0      : InstD8<0b1100011100000000,
+                            (outs), (ins disp8:$disp),
+                            "mov @($disp,PC),R0",
+                            []>;
+
+// mov.w @(disp,PC), Rn 
+let hasSideEffects = 0, mayLoad = 1 in
+def MOVWD8PCRn    : InstRnD8<0b1001000000000000,
+                            (outs GPR:$Rn), (ins disp8:$disp),
+                            "mov.w @($disp,PC),$Rn",
+                            [(set i32:$Rn, (sextloadi16 addr:$disp))]>;
+
+// mov.l @(disp,PC), Rn 
+let hasSideEffects = 0, mayLoad = 1 in
+def MOVLD8PCRn    : InstRnD8<0b1101000000000000,
+                            (outs GPR:$Rn), (ins disp8:$disp),
+                            "mov.l @($disp,PC),$Rn",
+                            [(set i32:$Rn, (load addr:$disp))]>;
+
+// movt Rn
+def MOVTRn          : InstRn<0b0000000000101001,
+                            (outs GPR:$Rn), (ins),
+                            "movt $Rn",
+                            []>;
 
-// mova @(disp,PC), R0
+// swap.b Rm,Rn
+def SWAPBRmRn     : InstRmRn<0b0110000000001000,
+                            (outs GPR:$Rn), (ins GPR:$Rm),
+                            "swap.b $Rm,$Rn",
+                            []>;
 
+// swap.w Rm,Rn
+def SWAPWRmRn     : InstRmRn<0b0110000000001001,
+                            (outs GPR:$Rn), (ins GPR:$Rm),
+                            "swap.w $Rm,$Rn",
+                            []>;
 
-//===----------------------------------------------------------------------===//
+// xtrct Rm,Rn
+def XTRCTRmRn     : InstRmRn<0b0010000000001101,
+                            (outs GPR:$Rn), (ins GPR:$Rm),
+                            "xtrct $Rm,$Rn",
+                            []>;
+
+//===--------------------------------------------------------------------------===//
 // Load Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 // Indirect Memory -> Register Load
 let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
- def MOVBRmiRn          : InstRmRn<0b0110000000000000,
+
+  // mov.b @Rm, Rn
+  def MOVBRmiRn         : InstRmRn<0b0110000000000000,
                                   (outs GPR:$Rn), (ins GPR:$Rm),
                                   "mov.b @$Rm,$Rn",
                                   [(set i32:$Rn, (sextloadi8 i32:$Rm))]>;
 
- def MOVWRmiRn          : InstRmRn<0b0110000000000001,
+  // mov.w @Rm, Rn
+  def MOVWRmiRn         : InstRmRn<0b0110000000000001,
                                   (outs GPR:$Rn), (ins GPR:$Rm),
                                   "mov.w @$Rm,$Rn",
                                   [(set i32:$Rn, (sextloadi16 i32:$Rm))]>;
 
- def MOVLRmiRn          : InstRmRn<0b0110000000000010,
+  // mov.l @Rm, Rn
+  def MOVLRmiRn         : InstRmRn<0b0110000000000010,
                                   (outs GPR:$Rn), (ins GPR:$Rm),
                                   "mov.l @$Rm,$Rn",
                                   [(set i32:$Rn, (load i32:$Rm))]>;
-}
- 
-// Indirect Memory w/ Displacement -> Register Load
-let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
-  def MOVLD4RmiRn    : InstRmD4Rn<0b0101000000000000,
+
+  // mov.b @Rm+, Rn
+  def MOVBRminciRn      : InstRmRn<0b0110000000000100,
+                                  (outs GPR:$Rn), (ins GPR:$Rm),
+                                  "mov.b @$Rm+,$Rn",
+                                  []>;
+
+  // mov.w @Rm+, Rn
+  def MOVWRminciRn      : InstRmRn<0b0110000000000101,
+                                  (outs GPR:$Rn), (ins GPR:$Rm),
+                                  "mov.w @$Rm+,$Rn",
+                                  []>;
+
+  // mov.l @Rm+, Rn
+  def MOVLRminciRn      : InstRmRn<0b0110000000000110,
+                                  (outs GPR:$Rn), (ins GPR:$Rm),
+                                  "mov.l @$Rm+,$Rn",
+                                  []>;
+
+  // mov.b @(disp, Rm), R0
+  let Defs = [R0] in
+  def MOVBD4RmiR0       : InstRmD4<0b1000010000000000,
+                                  (outs), (ins GPR:$Rm, disp4:$disp),
+                                  "mov.b @($disp,$Rm),R0",
+                                  []>;
+  
+  // mov.w @(disp, Rm), R0
+  let Defs = [R0] in
+  def MOVWD4RmiR0       : InstRmD4<0b1000010100000000,
+                                  (outs), (ins GPR:$Rm, disp4:$disp),
+                                  "mov.w @($disp,$Rm),R0",
+                                  []>;
+  
+  // mov.l @(disp, Rm), Rn
+  def MOVLD4RmiRn     : InstRmRnD4<0b0101000000000000,
                                   (outs GPRMem:$Rn), (ins GPR:$Rm, disp4:$disp),
-                                  "mov.l @($disp, $Rm),$Rn",
+                                  "mov.l @($disp,$Rm),$Rn",
+                                  []>;
+
+  // mov.b @(R0,Rm),Rn
+  let Uses = [R0] in
+  def MOVBR0RmiRn       : InstRmRn<0b0000000000001100,
+                                  (outs GPR:$Rn), (ins GPR:$Rm),
+                                  "mov.b @(R0,Rm),Rn",
+                                  []>;
+  
+  // mov.w @(R0,Rm),Rn
+  let Uses = [R0] in
+  def MOVWR0RmiRn       : InstRmRn<0b0000000000001101,
+                                  (outs GPR:$Rn), (ins GPR:$Rm),
+                                  "mov.w @(R0,$Rm),$Rn",
+                                  []>;
+  
+  // mov.l @(R0,Rm),Rn
+  let Uses = [R0] in
+  def MOVLR0RmiRn       : InstRmRn<0b0000000000001110,
+                                  (outs GPR:$Rn), (ins GPR:$Rm),
+                                  "mov.l @(R0,$Rm),$Rn",
                                   []>;
 
-                                  // "mov.l", [(set i32:$Rn, (load addr:$disp))]>;
+  // mov.b @(disp,GBR),R0
+  let Defs = [R0], Uses = [GBR] in
+  def MOVBD12GBRiR0       : InstD8<0b1100010000000000,
+                                  (outs), (ins disp12:$disp),
+                                  "mov.b @($disp,GBR),R0",
+                                  []>;
+  
+  // mov.w @(disp,GBR),R0
+  let Defs = [R0], Uses = [GBR] in
+  def MOVWD12GBRiR0       : InstD8<0b1100010100000000,
+                                  (outs), (ins disp12:$disp),
+                                  "mov.w @($disp,GBR),R0",
+                                  []>;
+  
+  // mov.l @(disp,GBR),R0
+  let Defs = [R0], Uses = [GBR] in
+  def MOVLD12GBRiR0       : InstD8<0b1100011000000000,
+                                  (outs), (ins disp12:$disp),
+                                  "mov.l @($disp,GBR),R0",
+                                  []>;
 }
 
 
-//===----------------------------------------------------------------------===//
+
+//===--------------------------------------------------------------------------===//
 // Store Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 // Register -> Indirect Memory Store
 let hasSideEffects = 0, mayStore = 1 in {
- def MOVBRmRni          : InstRmRn<0b0010000000000000,
+
+  // mov.b Rm, @Rn
+  def MOVBRmRni         : InstRmRn<0b0010000000000000,
                                   (outs), (ins GPRMem:$Rn, GPR:$Rm),
                                   "mov.b $Rm,@$Rn",
-                                  [(truncstorei8 GPRMem:$Rn, i32:$Rm)]>;
+                                  [(truncstorei8 i32:$Rm, GPRMem:$Rn)]>;
 
- def MOVWRmRni          : InstRmRn<0b0010000000000001,
-                                  (outs), (ins GPRMem:$Rn, GPR:$Rm),
+  // mov.w Rm, @Rn
+  def MOVWRmRni         : InstRmRn<0b0010000000000001,
+                                  (outs), (ins GPR:$Rm, GPRMem:$Rn),
                                   "mov.w $Rm,@$Rn",
-                                  [(truncstorei16 GPRMem:$Rn, i32:$Rm)]>;
+                                  [(truncstorei16 i32:$Rm, GPRMem:$Rn)]>;
 
- def MOVLRmRni          : InstRmRn<0b0010000000000010,
+  // mov.l Rm, @Rn
+  def MOVLRmRni         : InstRmRn<0b0010000000000010,
                                   (outs), (ins GPRMem:$Rn, GPR:$Rm),
                                   "mov.l $Rm,@$Rn",
-                                  [(store GPRMem:$Rn, i32:$Rm)]>;
+                                  [(store i32:$Rm, GPRMem:$Rn)]>;
+
+  // mov.b Rm, @-Rn
+  def MOVBRmRndeci      : InstRmRn<0b0010000000000100,
+                                  (outs), (ins GPRMem:$Rn, GPR:$Rm),
+                                  "mov.b $Rm, at -$Rn",
+                                  []>;
+
+  // mov.w Rm, @-Rn
+  def MOVWRmRndeci      : InstRmRn<0b0010000000000101,
+                                  (outs), (ins GPR:$Rm, GPRMem:$Rn),
+                                  "mov.w $Rm, at -$Rn",
+                                  []>;
+
+  // mov.l Rm, @-Rn
+  def MOVLRmRndeci      : InstRmRn<0b0010000000000110,
+                                  (outs), (ins GPRMem:$Rn, GPR:$Rm),
+                                  "mov.l $Rm, at -$Rn",
+                                  []>;
+  
+  // mov.b R0, @(disp, Rn)
+  let Uses = [R0] in
+  def MOVBR0D4Rni       : InstRnD4<0b1000000000000000,
+                                  (outs GPR:$Rn), (ins disp4:$disp),
+                                  "mov.b R0,@($disp,$Rn)",
+                                  []>;
+  
+  // mov.w R0, @(disp, Rn)
+  let Uses = [R0] in
+  def MOVWR0D4Rni       : InstRnD4<0b1000000100000000,
+                                  (outs GPR:$Rn), (ins disp4:$disp),
+                                  "mov.w R0,@($disp,$Rn)",
+                                  []>;
+  
+  // mov.l Rm, @(disp, Rn)
+  def MOVLRmD4Rni     : InstRmRnD4<0b0001000000000000,
+                                  (outs GPR:$Rn), (ins GPR:$Rm, disp4:$disp),
+                                  "mov.l $Rm,@($disp,$Rn)",
+                                  []>;
+
+  // mov.b Rm,@(R0,Rn)
+  let Uses = [R0] in
+  def MOVBRmR0Rni       : InstRmRn<0b0000000000000100,
+                                  (outs), (ins GPR:$Rm, GPR:$Rn),
+                                  "mov.b $Rm,@(R0,$Rn)",
+                                  []>;
+  
+  // mov.w Rm,@(R0,Rn)
+  let Uses = [R0] in
+  def MOVWRmR0Rni       : InstRmRn<0b0000000000000101,
+                                  (outs), (ins GPR:$Rm, GPR:$Rn),
+                                  "mov.w $Rm,@(R0,$Rn)",
+                                  []>;
+  
+  // mov.l Rm,@(R0,Rn)
+  let Uses = [R0] in
+  def MOVLRmR0Rni       : InstRmRn<0b0000000000000110,
+                                  (outs), (ins GPR:$Rm, GPR:$Rn),
+                                  "mov.l $Rm,@(R0,$Rn)",
+                                  []>;
+
+  // mov.b R0,@(disp,GBR)
+  let Uses = [R0, GBR] in
+  def MOVBR0D12GBRi       : InstD8<0b1100000000000000,
+                                  (outs), (ins disp12:$disp),
+                                  "mov.b R0,@($disp,GBR)",
+                                  []>;
+  
+  // mov.w R0,@(disp,GBR)
+  let Uses = [R0, GBR] in
+  def MOVWR0D12GBRi       : InstD8<0b1100000100000000,
+                                  (outs), (ins disp12:$disp),
+                                  "mov.w R0,@($disp,GBR)",
+                                  []>;
+  
+  // mov.l R0,@(disp,GBR)
+  let Uses = [R0, GBR] in
+  def MOVLR0D12GBRi       : InstD8<0b1100001000000000,
+                                  (outs), (ins disp12:$disp),
+                                  "mov.l R0,@($disp,GBR)",
+                                  []>;
 }
 
-//===----------------------------------------------------------------------===//
-// Arithmetic Instructions
-//===----------------------------------------------------------------------===//
 
-//
-//      ADDITION
-//
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                            Arithmetic Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+
+
+//===--------------------------------------------------------------------------===//
+// Addition
+//===--------------------------------------------------------------------------===//
+
 let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
   
   // add Rm, Rn
@@ -271,7 +512,7 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
                               [(set i32:$Rn, (add i32:$src, i32:$Rm))]>;
   
   // add imm:8, Rn
-  def ADDI8Rn       : InstI8Rn<0b0011000000001100, 
+  def ADDI8Rn       : InstRnI8<0b0011000000001100, 
                               (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
                               "add #$imm,$Rn",
                               [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
@@ -292,9 +533,12 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 
 }
 
-//
-//      SUBTRACTION
-//
+
+
+//===--------------------------------------------------------------------------===//
+// Subtraction
+//===--------------------------------------------------------------------------===//
+
 let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 
   // sub Rm, Rn
@@ -319,15 +563,12 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
   
   // dt Rn
   let Defs = [SR] in
-  def DTRmRn        : InstRn<0b0011000000001000,
-                            (outs GPR:$Rn), (ins GPR:$src),
-                            "dt $Rn",
-                            [(set i32:$Rn, (sub i32:$src, -1))]>;
+  def DTRn            : InstRn<0b0100000000010000,
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "dt $Rn",
+                              [(set i32:$Rn, (sub i32:$src, -1))]>;
 }
 
-//
-//      NEGATION
-//
 let hasSideEffects = 0 in {
 
   // neg Rm, Rn
@@ -345,9 +586,12 @@ let hasSideEffects = 0 in {
 
 }
 
-//
-//      MULTIPLY
-//
+
+
+//===--------------------------------------------------------------------------===//
+// Multiplication
+//===--------------------------------------------------------------------------===//
+
 let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 
   // mul.l Rm, Rn
@@ -366,9 +610,156 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 
 }
 
-//===----------------------------------------------------------------------===//
-// Branch Instructions
-//===----------------------------------------------------------------------===//
+
+
+
+//===--------------------------------------------------------------------------===//
+// Division
+//===--------------------------------------------------------------------------===//
+
+let hasSideEffects = 0, isCommutable = 1 in {
+
+  // div0s Rm, Rn
+  let Defs = [SR] in
+  def DIV0SRmRn     : InstRmRn<0b0010000000000111, 
+                              (outs), (ins GPR:$Rn, GPR:$Rm),
+                              "div0s $Rm,$Rn",
+                              []>;
+  
+  // div0u
+  let Defs = [SR] in
+  def DIV0U             : Inst<0b0000000000011001, 
+                              (outs), (ins),
+                              "div0u",
+                              []>;
+
+  // div1 Rm, Rn
+  let Defs = [SR] in
+  def DIV1RmRn      : InstRmRn<0b0011000000000100, 
+                              (outs GPR:$Rn), (ins GPR:$Rm),
+                              "div1 $Rm,$Rn",
+                              []>;
+}
+
+let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+
+  // Expand LLVM sdiv to the following sequence:
+  // div0s
+  // div1 Rm, Rn
+  def DIVSRmRn        : SHPseudo<(outs GPR:$Rn), 
+                                 (ins GPR:$Rm, GPR:$src),
+                                 "; divs $Rm, $Rn",
+                                 [(set i32:$Rn, (sdiv i32:$Rm, i32:$src))]>;
+
+  // Expand LLVM udiv to the following sequence:
+  // div0u
+  // div1 Rm, Rn
+  def DIVURmRn        : SHPseudo<(outs GPR:$Rn), 
+                                 (ins GPR:$Rm, GPR:$src),
+                                 "; divu $Rm, $Rn",
+                                 [(set i32:$Rn, (udiv i32:$Rm, i32:$src))]>;
+}
+
+
+
+
+//===--------------------------------------------------------------------------===//
+// Comparison
+//===--------------------------------------------------------------------------===//
+
+// cmp/eq #imm,R0
+let Defs = [R0, SR] in
+def CMPEQI8R0         : InstI8<0b1000100000000000,
+                              (outs), (ins imm8:$imm),
+                              "cmp/eq #imm,R0",
+                              []>;
+
+// cmp/eq Rm,Rn
+let Defs = [SR] in
+def CMPEQRmRn       : InstRmRn<0b0011000000000000,
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
+                              "cmp/eq $Rm,$Rn",
+                              []>;
+
+// cmp/hs Rm,Rn
+let Defs = [SR] in
+def CMPHSRmRn       : InstRmRn<0b0011000000000010,
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
+                              "cmp/hs $Rm,$Rn",
+                              []>;
+
+// cmp/ge Rm,Rn
+let Defs = [SR] in
+def CMPGERmRn       : InstRmRn<0b0011000000000011,
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
+                              "cmp/ge $Rm,$Rn",
+                              []>;
+
+// cmp/hi Rm,Rn
+let Defs = [SR] in
+def CMPHIRmRn       : InstRmRn<0b0011000000000110,
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
+                              "cmp/hi $Rm,$Rn",
+                              []>;
+
+// cmp/gt Rm,Rn
+let Defs = [SR] in
+def CMPGTRmRn       : InstRmRn<0b0011000000000111,
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
+                              "cmp/gt $Rm,$Rn",
+                              []>;
+
+// cmp/pl Rn
+let Defs = [SR] in
+def CMPPLRn           : InstRn<0b0100000000010101,
+                              (outs), (ins GPR:$Rn),
+                              "cmp/pl $Rn",
+                              []>;
+
+// cmp/pz Rn
+let Defs = [SR] in
+def CMPPZRn           : InstRn<0b0100000000010001,
+                              (outs), (ins GPR:$Rn),
+                              "cmp/pz $Rn",
+                              []>;
+
+// cmp/str Rm,Rn
+let Defs = [SR] in
+def CMPSTRRmRn      : InstRmRn<0b0010000000001100,
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
+                              "cmp/str $Rm,$Rn",
+                              []>;
+
+
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                        Logic Operation Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                              Shift Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                              Branch Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 // TODO: Port these to the updated way.
 // def BF_Disp      : BrOp_Disp8<0b1000101100000000, "bf">;
@@ -382,9 +773,9 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 // def JMP_Rmi        : BrOp_Rmi<0b0100000000101011, "jmp">;
 
 
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // Call Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 let isCall = 1 in {
   let Uses = [GBR] in
@@ -395,9 +786,9 @@ let isCall = 1 in {
 }
 
 
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // Return Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
   def RTS             : Inst<0b0000000000001011,
@@ -410,10 +801,19 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
 
 
 
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                          System Control Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
-//===----------------------------------------------------------------------===//
+
+
+
+
+//===--------------------------------------------------------------------------===//
 // Control Instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 // nop
 let hasSideEffects = 1 in
@@ -424,11 +824,16 @@ let hasSideEffects = 1 in
 def SLEEP : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
 
 
+//===--------------------------------------------------------------------------===//
+// Bigger Extensions
+//===--------------------------------------------------------------------------===//
+
+include "SuperHInstrDSP.td"
 
 
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 // Pseudo instructions
-//===----------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
 
 // Helper instruction for mapping frame indices to relative frame pointer
 // offsets.

>From 69192c7bb894ab516ed739026b21eaf999ef9856 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 10 Aug 2026 09:48:31 +0200
Subject: [PATCH 17/67] Add rt stubs for div, delay slots and more instrs

---
 compiler-rt/lib/builtins/superh/divhi3.S      |  24 +
 compiler-rt/lib/builtins/superh/divqi3.S      |  24 +
 compiler-rt/lib/builtins/superh/divsi3.S      |  24 +
 compiler-rt/lib/builtins/superh/udivhi3.S     |  24 +
 compiler-rt/lib/builtins/superh/udivqi3.S     |  24 +
 compiler-rt/lib/builtins/superh/udivsi3.S     |  24 +
 llvm/include/llvm/IR/RuntimeLibcalls.td       |  24 +
 llvm/lib/Target/SuperH/CMakeLists.txt         |   1 +
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |   9 +
 llvm/lib/Target/SuperH/SuperH.h               |   3 +
 llvm/lib/Target/SuperH/SuperHCallingConv.td   |  19 +-
 .../Target/SuperH/SuperHFillDelaySlots.cpp    | 138 ++++++
 .../lib/Target/SuperH/SuperHFrameLowering.cpp | 185 +++++++-
 llvm/lib/Target/SuperH/SuperHFrameLowering.h  |   2 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |   4 +-
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 289 +++++++++++-
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |   9 +
 llvm/lib/Target/SuperH/SuperHInstrDSP.td      |  12 +
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  69 +--
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |   3 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 432 ++++++++++++++++--
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp |  35 +-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.h   |   8 +-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.td  |   7 +-
 .../lib/Target/SuperH/SuperHTargetMachine.cpp |   6 +
 25 files changed, 1250 insertions(+), 149 deletions(-)
 create mode 100644 compiler-rt/lib/builtins/superh/divhi3.S
 create mode 100644 compiler-rt/lib/builtins/superh/divqi3.S
 create mode 100644 compiler-rt/lib/builtins/superh/divsi3.S
 create mode 100644 compiler-rt/lib/builtins/superh/udivhi3.S
 create mode 100644 compiler-rt/lib/builtins/superh/udivqi3.S
 create mode 100644 compiler-rt/lib/builtins/superh/udivsi3.S
 create mode 100644 llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
 create mode 100644 llvm/lib/Target/SuperH/SuperHInstrDSP.td

diff --git a/compiler-rt/lib/builtins/superh/divhi3.S b/compiler-rt/lib/builtins/superh/divhi3.S
new file mode 100644
index 0000000000000..4e63a33a1d715
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/divhi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+	.macro FUNCTION_BEGIN name
+	.text
+		.p2align 4
+	.globl \name
+	.type \name, @function
+\name:
+	.endm
+
+	.macro FUNCTION_END name
+	.size  \name, . - \name
+	.endm
+
+
+FUNCTION_BEGIN __sh_divhi3
+	
+FUNCTION_END __sh_divhi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/divqi3.S b/compiler-rt/lib/builtins/superh/divqi3.S
new file mode 100644
index 0000000000000..cb73cadb22103
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/divqi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+	.macro FUNCTION_BEGIN name
+	.text
+		.p2align 4
+	.globl \name
+	.type \name, @function
+\name:
+	.endm
+
+	.macro FUNCTION_END name
+	.size  \name, . - \name
+	.endm
+
+
+FUNCTION_BEGIN __sh_divqi3
+	
+FUNCTION_END __sh_divqi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/divsi3.S b/compiler-rt/lib/builtins/superh/divsi3.S
new file mode 100644
index 0000000000000..07da658506941
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/divsi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+	.macro FUNCTION_BEGIN name
+	.text
+		.p2align 4
+	.globl \name
+	.type \name, @function
+\name:
+	.endm
+
+	.macro FUNCTION_END name
+	.size  \name, . - \name
+	.endm
+
+
+FUNCTION_BEGIN __sh_divsi3
+	
+FUNCTION_END __sh_divsi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivhi3.S b/compiler-rt/lib/builtins/superh/udivhi3.S
new file mode 100644
index 0000000000000..4eda163340250
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/udivhi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+	.macro FUNCTION_BEGIN name
+	.text
+		.p2align 4
+	.globl \name
+	.type \name, @function
+\name:
+	.endm
+
+	.macro FUNCTION_END name
+	.size  \name, . - \name
+	.endm
+
+
+FUNCTION_BEGIN __sh_udivhi3
+	
+FUNCTION_END __sh_udivhi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivqi3.S b/compiler-rt/lib/builtins/superh/udivqi3.S
new file mode 100644
index 0000000000000..1c03576115a40
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/udivqi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+	.macro FUNCTION_BEGIN name
+	.text
+		.p2align 4
+	.globl \name
+	.type \name, @function
+\name:
+	.endm
+
+	.macro FUNCTION_END name
+	.size  \name, . - \name
+	.endm
+
+
+FUNCTION_BEGIN __sh_udivqi3
+	
+FUNCTION_END __sh_udivqi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivsi3.S b/compiler-rt/lib/builtins/superh/udivsi3.S
new file mode 100644
index 0000000000000..22386367f52ba
--- /dev/null
+++ b/compiler-rt/lib/builtins/superh/udivsi3.S
@@ -0,0 +1,24 @@
+//===---------------------- SuperH builtin routine ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+	.macro FUNCTION_BEGIN name
+	.text
+		.p2align 4
+	.globl \name
+	.type \name, @function
+\name:
+	.endm
+
+	.macro FUNCTION_END name
+	.size  \name, . - \name
+	.endm
+
+
+FUNCTION_BEGIN __sh_udivsi3
+	
+FUNCTION_END __sh_udivsi3
\ No newline at end of file
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 46b9aba86ddd6..bca71605a921b 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -3385,6 +3385,30 @@ def SPARCSystemLibrary
        AvailableIf<__stack_chk_guard, isNotOSLinuxAndNotOSOpenBSD>)
 >;
 
+//===----------------------------------------------------------------------===//
+// SuperH Runtime Libcalls
+//===----------------------------------------------------------------------===//
+
+defset list<RuntimeLibcallImpl> SuperHRuntimeLibcalls = {
+def __sh_divqi3 : RuntimeLibcallImpl<SDIV_I8>;
+def __sh_divhi3 : RuntimeLibcallImpl<SDIV_I16>;
+def __sh_divsi3 : RuntimeLibcallImpl<SDIV_I32>;
+def __sh_udivqi3 : RuntimeLibcallImpl<UDIV_I8>;
+def __sh_udivhi3 : RuntimeLibcallImpl<UDIV_I16>;
+def __sh_udivsi3 : RuntimeLibcallImpl<UDIV_I32>;
+}
+
+defvar SuperH_DivCalls = [
+  __divqi3, __divhi3, __divsi3, __udivqi3, __udivhi3, __udivsi3
+];
+
+def isSuperH : RuntimeLibcallPredicate<"TT.isSuperH()">;
+def SuperHSystemLibrary 
+      : SystemRuntimeLibrary<isSuperH,
+                            (add (sub DefaultLibcallImpls32, SuperH_DivCalls),
+                            LibcallImpls<(add SuperHRuntimeLibcalls)>)
+>;
+
 //===----------------------------------------------------------------------===//
 // SPIRV Runtime Libcalls
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index 535e9d53b2853..a67293ce502f4 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -27,6 +27,7 @@ add_llvm_target(SuperHCodeGen
   SuperHAsmPrinter.cpp
   SuperHInstrInfo.cpp
   SuperHSubtarget.cpp
+  SuperHFillDelaySlots.cpp
 
   LINK_COMPONENTS
   Analysis
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 3ddbb766796f1..987b0594cf813 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -13,7 +13,9 @@
 
 #include "SuperHInstPrinter.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/Debug.h"
 
 using namespace llvm;
@@ -53,6 +55,13 @@ void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostrea
 		O << Op.getImm();
 		return;
 	}
+
+	// Print symbol references
+	if (Op.isBareSymbolRef()) {
+		const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
+		O << SymOp->getSymbol().getName();
+		return;
+	}
 }
 
 void SuperHInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index 75fdde6c8b6a0..c0d62f8fb03f8 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -26,9 +26,12 @@ class PassRegistry;
 class SuperHTargetMachine;
 
 FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel);
+FunctionPass *createSuperHFillDelaySlotsPass();
 
 void initializeSuperHDAGToDAGISelLegacyPass(PassRegistry &);
 void initializeSuperHAsmPrinterPass(PassRegistry &);
+void initializeSuperHAsmPrinterPass(PassRegistry &);
+void initializeSuperHFillDelaySlotsPass(PassRegistry &);
 } // namespace llvm
 
 
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index 6ce14d5d0c8a9..429bd8be41908 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -13,20 +13,23 @@
 //===-------------------------------------------------------------------------===//
 
 def CC_SH : CallingConv<[
-  CCIfSRet<CCCustom<"RetCC_SuperH_SRet">>,
 
-  // Handles byval parameters.
-  CCIfByVal<CCPassByVal<4, 4>>,
+  // All lower size parameters are promoted to 32-bit
   CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
-
   CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
-  CCIfType<[i32], CCAssignToStack<4, 4>>,
-  CCIfType<[f32], CCAssignToStack<4, 4>>,
 ]>;
 
 def RetCC_SH : CallingConv<[
-  CCIfType<[i32],  CCAssignToReg<[R0]>>,
-  CCIfType<[i64],  CCAssignToReg<[R0, R1]>>
+  CCIfSRet<CCCustom<"RetCC_SuperH_SRet">>,
+
+  // All lower size parameters are promoted to 32-bit
+  CCIfType<[i1, i8, i16],  CCPromoteToType<i32>>,
+  CCIfType<[i32],  CCAssignToReg<[R0, R1, R2, R3]>>,
+  CCIfType<[i64],  CCAssignToReg<[R0, R1]>>,
+
+  // Anything that doesn't fit in registers should be spilled.
+  CCIfType<[i32], CCAssignToStack<4, 4>>,
+  CCIfType<[i64], CCAssignToStack<8, 8>>,
 ]>;
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
new file mode 100644
index 0000000000000..f96038e3b9cb7
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -0,0 +1,138 @@
+//===-- SuperHFillDelaySlots.cpp - Reordering pass to fill delay slots ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that fills delay slots of branching instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperH.h"
+#include "SuperHInstrInfo.h"
+#include "SuperHTargetMachine.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/Support/DebugLog.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-fill-delay-slots"
+#define SUPERH_FILL_DELAY_SLOTS_NAME "SuperH delay slot filling pass"
+
+namespace {
+class SuperHFillDelaySlots : public MachineFunctionPass {
+public:
+  static char ID;
+
+  SuperHFillDelaySlots() : MachineFunctionPass(ID) {}
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  StringRef getPassName() const override { return SUPERH_FILL_DELAY_SLOTS_NAME; }
+
+private:
+  typedef MachineBasicBlock Block;
+  typedef Block::iterator BlockIt;
+
+  const SuperHRegisterInfo *TRI;
+  const TargetInstrInfo *TII;
+
+  bool hasDelaySlot(MachineInstr &I);
+  bool expandMBB(Block &MBB);
+  bool expandMI(Block &MBB, BlockIt MBBI);
+
+  // Expansion functions
+  bool fillDelaySlot(Block &MBB, BlockIt MBBI);
+};
+
+} // end namespace
+
+
+bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
+  MachineInstr &MI = *MBBI;
+  if (auto *Prev = MBBI->getPrevNode()) {
+
+    // If the prior instruction does not have a delay slot
+    // we swap the instructions.
+    //
+    // NOTE:  SuperH does not allow branch instructions
+    //        of any kind to be situated in a delay slot.
+    //        as such we fall through to the NOP in that
+    //        instance.
+    if (!Prev->isBranch() && !Prev->hasDelaySlot()) {
+      LDBG() << "Swapping " << TII->getName(MI.getOpcode()) 
+             << " and " << TII->getName(Prev->getOpcode()) 
+             << " @ " << MBB.getParent()->getName();
+      MBB.insertAfter(MBBI, Prev->removeFromParent());
+      return true;
+    }
+  }
+
+  LDBG() << "Inserting NOP after " << TII->getName(MI.getOpcode())
+         << " @ " << MBB.getParent()->getName();
+
+  // Otherwise just insert a NOP.
+  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(SH::NOP));
+  return true;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//                                HELPERS
+//===----------------------------------------------------------------------===//
+
+bool SuperHFillDelaySlots::expandMI(Block &MBB, BlockIt MBBI) {
+  MachineInstr &MI = *MBBI;
+
+  if (MI.hasDelaySlot()) {
+    return fillDelaySlot(MBB, MBBI);
+  }
+  return false;
+}
+
+bool SuperHFillDelaySlots::expandMBB(Block &MBB) {
+  bool Modified = false;
+
+  BlockIt MBBI = MBB.begin(), E = MBB.end();
+  while (MBBI != E) {
+    BlockIt NMBBI = std::next(MBBI);
+    Modified |= expandMI(MBB, MBBI);
+    MBBI = NMBBI;
+  }
+
+  return Modified;
+}
+
+bool SuperHFillDelaySlots::runOnMachineFunction(MachineFunction &MF) {
+  bool Modified = false;
+
+  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+  TRI = STI.getRegisterInfo();
+  TII = STI.getInstrInfo();
+
+  for (Block &MBB : MF) {
+    Modified |= expandMBB(MBB);
+  }
+
+  return Modified;
+}
+
+
+char SuperHFillDelaySlots::ID = 0;
+
+INITIALIZE_PASS(SuperHFillDelaySlots, "sh-fill-delay-slots", SUPERH_FILL_DELAY_SLOTS_NAME,
+                false, false)
+
+FunctionPass *llvm::createSuperHFillDelaySlotsPass() {
+  return new SuperHFillDelaySlots();
+}
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index a96ea010c27ab..5db9816b1ca2d 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -13,42 +13,203 @@
 
 
 #include "SuperHFrameLowering.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "SuperHInstrInfo.h"
+#include "SuperHRegisterInfo.h"
 #include "SuperHSubtarget.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugLog.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define DEBUG_TYPE "sh-framelowering"
 
 using namespace llvm;
 
-void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+// Get amount of times to shift the value in a SP adjustment
+// for it to fit.
+static unsigned getShiftAmt(uint32_t Val) {
+  unsigned R = 0;
+  for(unsigned i = 0; i < 4; i++) {
+    if (((Val >> (i*8)) & 0xFF))
+      R = i;
+  }
+  return R;
+}
+
+// Helper to emit stack pointer adjustment.
+static void emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasicBlock::iterator MBBI, int32_t AdjValue) {
+  DebugLoc dl;
+  const SuperHInstrInfo &TII = *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
+  const SuperHRegisterInfo &RII = *static_cast<const SuperHRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
+  MachineInstr::MIFlag MFlag = AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
+
+  Register SP = RII.getStackRegister();
+
+  if (AdjValue < 255) {
+
+    // Fast path, emit a single immediate add.
+    //    Emit add #-(size),r15
+    BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
+      .addImm((int)AdjValue)
+      .addReg(SP);
 
-  // If function is naked, don't emit prologue.
-  if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
     return;
   }
 
+  // Slow path, shift 8 bits at a time into r0.
+  unsigned ToShift = getShiftAmt(AdjValue);
+
+  // Empty R0 in case it had something.
+  BuildMI(MBB, MBBI, dl, TII.get(SH::MOVI8Rn), SH::R0)
+    .addImm(0)
+    .addReg(SH::R0)
+    .setMIFlag(MFlag);
+
+  // Shift value in with the following pattern:
+  //  or #(byte), r0
+  //  shll8 r0
+  for(unsigned i = 0; i < ToShift; i++) {
+    BuildMI(MBB, MBBI, dl, TII.get(SH::ORI8R0))
+      .addImm((AdjValue >> (i*8)) & 0xFF)
+      .setMIFlag(MFlag);
+    BuildMI(MBB, MBBI, dl, TII.get(SH::SHLL8Rn), SH::R0)
+      .addReg(SH::R0)
+      .setMIFlag(MFlag);
+  }
+
+  // Finally negate and add to r15.
+  //  neg r0, r0 (if negative displacement)
+  //  add r0, r15
+  if (AdjValue < 0)
+    BuildMI(MBB, MBBI, dl, TII.get(SH::NEGRmRn), SH::R0)
+      .addReg(SH::R0)
+      .addReg(SH::R0)
+      .setMIFlag(MFlag);
+
+  BuildMI(MBB, MBBI, dl, TII.get(SH::SUBRmRn), SP)
+    .addReg(SH::R0, RegState::Kill)
+    .addReg(SP)
+    .setMIFlag(MFlag);
+}
+
+void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+  MachineBasicBlock::iterator MBBI = MBB.begin();
+  MachineFrameInfo &MFI = MF.getFrameInfo();
+  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+  const SuperHInstrInfo &TII = *STI.getInstrInfo();
+  const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+  DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
+  bool HasFP = hasFP(MF);
+
+  Register SP = RII.getStackRegister();
+  Register FP = RII.getFrameRegister();
+
+  LDBG() << "emitPrologue";
+
+  // Realign stack
+  uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
+  MFI.setStackSize(StackSize);
+
+  // 1. Create stack frame
+  emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
+
+  // TODO: Create working register set.
+
+  // 3. Save return address to stack.
+  BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+    .addReg(SP)
+    .setMIFlag(MachineInstr::FrameSetup);
+
+  // 4. Establish frame pointer
+  if (HasFP) {
+    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+      .addReg(SP)
+      .setMIFlag(MachineInstr::FrameSetup);
+  }
+
+  // TODO: Establish GCP?
 }
 
 void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+  const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+  Register SP = RII.getStackRegister();
+  Register FP = RII.getFrameRegister();
+  
+  LDBG() << "emitEpilogue";
 
-  // If function is naked, don't emit epilogue.
-  if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
+  // Early exit if we have no frame pointer.
+  if (!hasFP(MF)) {
     return;
   }
+
+
+  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
+  MachineFrameInfo &MFI = MF.getFrameInfo();
+  DebugLoc DL = MBBI->getDebugLoc();
+  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+  const SuperHInstrInfo &TII = *STI.getInstrInfo();
+
+  uint32_t StackSize = MFI.getStackSize();
+
+  // TODO: Restore callee save registers
+
+  // 2. Restore return address from stack
+  BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+    .addReg(SP)
+    .setMIFlag(MachineInstr::FrameDestroy);
+
+  // 3. Delete stack frame, restoring stack pointer.
+  emitSPAdj(MF, MBB, MBBI, StackSize);
 }
 
-bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+MachineBasicBlock::iterator
+SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF, 
+                            MachineBasicBlock &MBB,
+                            MachineBasicBlock::iterator MI) const {
+  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+  const SuperHInstrInfo &TII = *STI.getInstrInfo();
+
+  LDBG() << "eliminateCallFramePseudoInstr";
+
+  // If call frame is reserved, erase.
+  if (hasReservedCallFrame(MF)) {
+    return MBB.erase(MI);
+  }
+
+  // If frame size is 0, erase.
+  int Amount = TII.getFrameSize(*MI);
+  if (Amount == 0) {
+    return MBB.erase(MI);
+  }
+
+  DebugLoc DL = MI->getDebugLoc();
+  unsigned int Opcode = MI->getOpcode();
+  if (Opcode == TII.getCallFrameSetupOpcode()) {
+    LDBG() << "eliminateCallFramePseudoInstr->CallFrameSetup";
+  } else {
+    LDBG() << "eliminateCallFramePseudoInstr->CallFrameDestroy";
+    assert(Opcode == TII.getCallFrameDestroyOpcode());
+
+  }
+
+  return MBB.erase(MI);
+}
+
+bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  return hasFP(MF) && !MFI.hasVarSizedObjects();
+  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
+         MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
 }
 
-MachineBasicBlock::iterator
-SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
-                            MachineBasicBlock::iterator I) const {
-	return MBB.erase(I);
+bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  return !MFI.hasVarSizedObjects();
 }
 
 void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
                         RegScavenger *RS) const {
-
+  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index c303baa4311d1..dd2cc63aaa32e 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -43,7 +43,7 @@ class SuperHFrameLowering : public TargetFrameLowering {
   void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
                             RegScavenger *RS) const override;
 protected:
-  bool hasFPImpl(const MachineFunction &MF) const override { return false; }
+  bool hasFPImpl(const MachineFunction &MF) const override;
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index d14e187479bb3..5c5f851ec4a72 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -117,7 +117,7 @@ bool SuperHDAGToDAGISel::trySelectRET(SDNode *N) {
   Ops.push_back(Chain.getValue(1));
 
   SDNode *ResNode = CurDAG->getMachineNode(SH::RTS, DL, MVT::Other, Ops);
-  ResNode = CurDAG->getMachineNode(SH::NOP, DL, MVT::Other, SDValue(ResNode, 0));
+  //ResNode = CurDAG->getMachineNode(SH::NOP, DL, MVT::Other, SDValue(ResNode, 0));
 
   ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
   CurDAG->RemoveDeadNode(N);
@@ -140,7 +140,7 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
   switch(Opcode) {
   case ISD::FrameIndex:
     return trySelectFrameIndex(N);
-  case SHISD::RET:
+  case SHISD::RET_GLUE:
     return trySelectRET(N);
   default:
     return false;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 46346fe72f9a3..39304e493a23d 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -18,8 +18,11 @@
 #include "SuperHTargetMachine.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/FunctionLoweringInfo.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/Support/DebugLog.h"
 
 using namespace llvm;
@@ -47,8 +50,28 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
 
   // GPR Registers are always 32 bit on SuperH.
   addRegisterClass(MVT::i32, &SH::GPRRegClass);
+  setSchedulingPreference(Sched::RegPressure);
+  setSupportsUnalignedAtomics(false);
   computeRegisterProperties(Subtarget->getRegisterInfo());
 
+  // Loads and stores are legal
+  for (MVT VT : MVT::integer_valuetypes()) {
+    for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
+      setLoadExtAction(N, VT, MVT::i1, Promote);
+      setLoadExtAction(N, VT, MVT::i8, Promote);
+      setLoadExtAction(N, VT, MVT::i16, Promote);
+    }
+  }
+
+  // Division and remainders are multi-instruction sequences
+  // on SuperH. Use a custom pass to lower those.
+  for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
+    setOperationAction(ISD::UDIV, VT, Custom);
+    setOperationAction(ISD::UREM, VT, Custom);
+    setOperationAction(ISD::SDIV, VT, Custom);
+    setOperationAction(ISD::SREM, VT, Custom);
+  }
+
 
   setBooleanContents(ZeroOrOneBooleanContent);
   setBooleanVectorContents(ZeroOrOneBooleanContent);
@@ -132,6 +155,9 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
   return Chain;
 }
 
+
+
+
 //===----------------------------------------------------------------------===//
 //                              RETURN LOWERING
 //===----------------------------------------------------------------------===//
@@ -170,7 +196,7 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
   }
 
-  // If function is naked, don't emit rts.
+  // If function is naked, don't emit return glue.
   if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
     return Chain;
   }
@@ -180,14 +206,265 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
   if (Glue.getNode())
     RetOps.push_back(Glue);
 
-  return DAG.getNode(SHISD::RET, dl, MVT::Other, RetOps);
+  return DAG.getNode(SHISD::RET_GLUE, dl, MVT::Other, RetOps);
 }
 
+
+
+
+//===----------------------------------------------------------------------===//
+//                              CALL LOWERING
+//===----------------------------------------------------------------------===//
+
 SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const {
-  for(unsigned i = 0; i < CLI.Ins.size(); i++) {
-    auto VArg = CLI.getArgs()[i];
-    InVals.push_back(VArg.Node);
+  SelectionDAG &DAG = CLI.DAG;
+  MachineFunction &MF = DAG.getMachineFunction();
+  SDLoc &DL = CLI.DL;
+  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
+  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+  SDValue Chain = CLI.Chain;
+  SDValue Callee = CLI.Callee;
+  bool &isTailCall = CLI.IsTailCall;
+  CallingConv::ID CallConv = CLI.CallConv;
+  bool isVarArg = CLI.IsVarArg;
+
+  // TODO: This was all yoinked from AVR, it likely needs to be modified to fit the calling
+  // convention of SuperH.
+
+  // Tail Call Optimisation not supported yet.
+  isTailCall = false;
+  isVarArg = false;
+
+  // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
+  // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
+  // node so that legalize doesn't hack it.
+  const Function *F = nullptr;
+  if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+    const GlobalValue *GV = G->getGlobal();
+    if (isa<Function>(GV))
+      F = cast<Function>(GV);
+    Callee =
+        DAG.getTargetGlobalAddress(GV, DL, getPointerTy(DAG.getDataLayout()));
+  } else if (const ExternalSymbolSDNode *ES =
+                 dyn_cast<ExternalSymbolSDNode>(Callee)) {
+    Callee = DAG.getTargetExternalSymbol(ES->getSymbol(),
+                                         getPointerTy(DAG.getDataLayout()));
+  }
+
+  if (isVarArg) {
+    return Chain;
+  }
+
+  // Analyze operands of the call, assigning locations to each operand.
+  SmallVector<CCValAssign, 16> ArgLocs;
+  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
+                 *DAG.getContext());
+
+  // Get a count of how many bytes are to be pushed on the stack.
+  unsigned NumBytes = CCInfo.getStackSize();
+  Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL);
+  SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
+
+  // First, walk the register assignments, inserting copies.
+  unsigned AI, AE;
+  bool HasStackArgs = false;
+  for (AI = 0, AE = ArgLocs.size(); AI != AE; ++AI) {
+    CCValAssign &VA = ArgLocs[AI];
+    EVT RegVT = VA.getLocVT();
+    SDValue Arg = OutVals[AI];
+
+    // Stop when we encounter a stack argument, we need to process them
+    // in reverse order in the loop below.
+    if (VA.isMemLoc()) {
+      HasStackArgs = true;
+      break;
+    }
+
+    // Arguments that can be passed on registers must be kept in the RegsToPass
+    // vector.
+    RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
+  }
+
+  // Second, stack arguments have to walked.
+  // Previously this code created chained stores but those chained stores appear
+  // to be unchained in the legalization phase. Therefore, do not attempt to
+  // chain them here. In fact, chaining them here somehow causes the first and
+  // second store to be reversed which is the exact opposite of the intended
+  // effect.
+  if (HasStackArgs) {
+    SmallVector<SDValue, 8> MemOpChains;
+    for (; AI != AE; AI++) {
+      CCValAssign &VA = ArgLocs[AI];
+      SDValue Arg = OutVals[AI];
+
+      assert(VA.isMemLoc());
+
+      // SP points to one stack slot further so add one to adjust it.
+      SDValue PtrOff = DAG.getNode(
+          ISD::ADD, DL, getPointerTy(DAG.getDataLayout()),
+          DAG.getRegister(SH::R15, getPointerTy(DAG.getDataLayout())),
+          DAG.getIntPtrConstant(VA.getLocMemOffset() + 1, DL));
+
+      MemOpChains.push_back(
+          DAG.getStore(Chain, DL, Arg, PtrOff,
+                       MachinePointerInfo::getStack(MF, VA.getLocMemOffset())));
+    }
+
+    if (!MemOpChains.empty())
+      Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
+  }
+
+  // Build a sequence of copy-to-reg nodes chained together with token chain and
+  // flag operands which copy the outgoing args into registers.  The InGlue in
+  // necessary since all emited instructions must be stuck together.
+  SDValue InGlue;
+  for (auto Reg : RegsToPass) {
+    Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, InGlue);
+    InGlue = Chain.getValue(1);
+  }
+
+  // Returns a chain & a flag for retval copy to use.
+  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
+  SmallVector<SDValue, 8> Ops;
+  Ops.push_back(Chain);
+  Ops.push_back(Callee);
+
+  // Add argument registers to the end of the list so that they are known live
+  // into the call.
+  for (auto Reg : RegsToPass) {
+    Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
+  }
+
+  // The zero register (usually R1) must be passed as an implicit register so
+  // that this register is correctly zeroed in interrupts.
+  Ops.push_back(DAG.getRegister(SH::R0, MVT::i32));
+
+  // Add a register mask operand representing the call-preserved registers.
+  const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
+  const uint32_t *Mask =
+      TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
+  assert(Mask && "Missing call preserved mask for calling convention");
+  Ops.push_back(DAG.getRegisterMask(Mask));
+
+  if (InGlue.getNode()) {
+    Ops.push_back(InGlue);
+  }
+
+  Chain = DAG.getNode(SHISD::CALL, DL, NodeTys, Ops);
+  InGlue = Chain.getValue(1);
+
+  // Create the CALLSEQ_END node.
+  Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
+
+  if (!Ins.empty()) {
+    InGlue = Chain.getValue(1);
+  }
+
+  return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, DL, DAG, InVals);
+}
+
+SDValue SuperHTargetLowering::LowerCallResult(
+    SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
+    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
+    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+
+  // Assign locations to each value returned by this call.
+  SmallVector<CCValAssign, 16> RVLocs;
+  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
+                 *DAG.getContext());
+
+  // Handle runtime calling convs.
+  CCInfo.AnalyzeCallResult(Ins, RetCC_SH);
+
+  // Copy all of the result registers out of their specified physreg.
+  for (CCValAssign const &RVLoc : RVLocs) {
+    Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(), InGlue)
+                .getValue(1);
+    InGlue = Chain.getValue(2);
+    InVals.push_back(Chain.getValue(0));
   }
 
-  return CLI.Chain;
+  return Chain;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                              DIVISION LOWERING
+//===----------------------------------------------------------------------===//
+
+SDValue SuperHTargetLowering::LowerDiv(SDValue Op, SelectionDAG &DAG) const {
+  unsigned Opcode = Op->getOpcode();
+  assert((Opcode == ISD::SDIV || Opcode == ISD::UDIV) &&
+         "Invalid opcode for Div lowering");
+  bool IsSigned = (Opcode == ISD::SDIV);
+  EVT VT = Op->getValueType(0);
+  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
+
+  RTLIB::Libcall LC;
+  switch (VT.getSimpleVT().SimpleTy) {
+  default:
+    llvm_unreachable("Unexpected request for libcall!");
+  case MVT::i8:
+    LC = IsSigned ? RTLIB::SDIV_I8 : RTLIB::UDIV_I8;
+    break;
+  case MVT::i16:
+    LC = IsSigned ? RTLIB::SDIV_I16 : RTLIB::UDIV_I16;
+    break;
+  case MVT::i32:
+    LC = IsSigned ? RTLIB::SDIV_I32 : RTLIB::UDIV_I32;
+    break;
+  }
+
+  SDValue InChain = DAG.getEntryNode();
+
+  TargetLowering::ArgListTy Args;
+  for (SDValue const &Value : Op->op_values()) {
+    TargetLowering::ArgListEntry Entry(
+        Value, Value.getValueType().getTypeForEVT(*DAG.getContext()));
+    Entry.IsSExt = IsSigned;
+    Entry.IsZExt = !IsSigned;
+    Args.push_back(Entry);
+  }
+
+  RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
+  if (LCImpl == RTLIB::Unsupported)
+    return SDValue();
+
+  SDValue Callee =
+      DAG.getExternalSymbol(LCImpl, getPointerTy(DAG.getDataLayout()));
+
+  Type *RetTy = (Type *)StructType::get(Ty, Ty);
+
+
+  SDLoc dl(Op);
+  TargetLowering::CallLoweringInfo CLI(DAG);
+  CLI.setDebugLoc(dl)
+      .setChain(InChain)
+      .setLibCallee(DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy,
+                    Callee, std::move(Args))
+      .setInRegister()
+      .setSExtResult(IsSigned)
+      .setZExtResult(!IsSigned);
+
+  std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
+  return CallInfo.first;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                              CUSTOM LOWERING
+//===----------------------------------------------------------------------===//
+
+SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
+  switch(Op->getOpcode()) {
+  case ISD::UDIV:
+  case ISD::SDIV:
+    return LowerDiv(Op, DAG);
+  }
+  return SDValue();
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 4617740b75c6d..e23143b989fe5 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -38,6 +38,15 @@ class SuperHTargetLowering : public TargetLowering  {
                       const Type *RetTy) const override;
   SDValue LowerCall(CallLoweringInfo &/*CLI*/,
               SmallVectorImpl<SDValue> &/*InVals*/) const override;
+
+  SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
+
+  // Custom Lowerings
+  SDValue LowerDiv(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerCallResult(
+    SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
+    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
+    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const;
 public:
   SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
 };
diff --git a/llvm/lib/Target/SuperH/SuperHInstrDSP.td b/llvm/lib/Target/SuperH/SuperHInstrDSP.td
new file mode 100644
index 0000000000000..ef23b0eaccdc9
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrDSP.td
@@ -0,0 +1,12 @@
+//===-- SuperHInstrDSP.td - DSP SuperH Instruction Definition --*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-------------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes the DSP extensions for the SuperH Instruction Set.
+///
+//===-------------------------------------------------------------------------===//
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 9b76cd1d4a9b6..8489d91f8ac85 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -52,65 +52,20 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   llvm_unreachable("Impossible reg-to-reg copy");
 }
 
-bool SuperHInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
-  unsigned OpCode = MI.getOpcode();
-  switch(OpCode) {
-  case SH::DIVURmRn:
-  case SH::DIVSRmRn:
-    return expandDIV(OpCode, MI);
-  default:
-    return false;
-  }
-}
-
-
+bool SuperHInstrInfo::expandRET(MachineInstr &MI) const {
+  MachineBasicBlock &MBB = *MI.getParent();
+  MachineBasicBlock::iterator MBBI = MI.getIterator();
+  DebugLoc DL = MI.getDebugLoc();
 
 
+  BuildMI(MBB, MBBI, DL, get(SH::NOP));
+  return true;
+}
 
-//===----------------------------------------------------------------------===//
-//                        Pseudo Instruction Expansion
-//===----------------------------------------------------------------------===//
-
-// Expands the division psuedo instructions into valid SuperH sequences.
-// SuperH sets the division mode with an struction inserted before.
-bool SuperHInstrInfo::expandDIV(unsigned Opcode, MachineInstr &MI) const {
-  assert(MI.getOperand(0).isReg() && "Expected register in op0 for expansion!");
-  assert(MI.getOperand(1).isReg() && "Expected register in op1 for expansion!");
-  auto &MBB = *MI.getParent();
-  auto Lhs = MI.getOperand(0).getReg();
-  auto Rhs = MI.getOperand(1).getReg();
-  auto DL = MI.getDebugLoc();
-
-  switch(Opcode) {
-
-  // Expand DIVURmRn to the following sequence:
-  // div0u
-  // div1 Rm, Rn
-  case SH::DIVURmRn: {
-    BuildMI(MBB, MI, DL, get(SH::DIV0U));
-    BuildMI(MBB, MI, DL, get(SH::DIV1RmRn), Rhs)
-      .addReg(Lhs);
-    MI.removeFromParent();
-    return true;
-  }
-
-  // Expand DIVSRmRn to the following sequence:
-  // div0s Rm, Rn
-  // div1 Rm, Rn
-  case SH::DIVSRmRn: {
-    BuildMI(MBB, MI, DL, get(SH::DIV0SRmRn))
-      .addReg(Rhs)
-      .addReg(Lhs);
-    BuildMI(MBB, MI, DL, get(SH::DIV1RmRn), Rhs)
-      .addReg(Lhs);
-    MI.removeFromParent();
-    return true;
-  }
-
-  // This shouldn't be reached.
-  default: {
-    llvm_unreachable("expandDIV was wrongfully called on a non-div pseudo!");
-    return false; 
-  }
+bool SuperHInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
+  switch(MI.getOpcode()) {
+  case SH::RTS:
+    return expandRET(MI);
   }
+  return false;
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index ae47b75d7ffc0..bbd95d0148c89 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -44,7 +44,8 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   bool expandPostRAPseudo(MachineInstr &MI) const override;
 
 private:
-  bool expandDIV(unsigned Opcode, MachineInstr &MI) const;
+  // Custom expansions
+  bool expandRET(MachineInstr &MI) const;
 };
 
 const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 4a8414f16f11a..32f27707ddf78 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -63,7 +63,7 @@ def SHCall          : SDNode<"SHISD::CALL", SHSDT_Call,
                             [SDNPHasChain, SDNPOutGlue,
                              SDNPOptInGlue, SDNPVariadic]>;
 
-def SHRet           : SDNode<"SHISD::RET", SDTNone,
+def SHRetGlue       : SDNode<"SHISD::RET_GLUE", SDTNone,
                             [SDNPHasChain, SDNPOptInGlue, 
                              SDNPVariadic]>;
 
@@ -503,33 +503,34 @@ let hasSideEffects = 0, mayStore = 1 in {
 // Addition
 //===--------------------------------------------------------------------------===//
 
-let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+let hasSideEffects = 0, Constraints = "$src = $Rn" in {
   
   // add Rm, Rn
+  let isCommutable = 1 in
   def ADDRmRn       : InstRmRn<0b0011000000001100, 
-                              (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "add $Rm,$Rn",
-                              [(set i32:$Rn, (add i32:$src, i32:$Rm))]>;
+                              [(set i32:$Rn, (add i32:$Rm, i32:$src))]>;
   
   // add imm:8, Rn
   def ADDI8Rn       : InstRnI8<0b0011000000001100, 
-                              (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
+                              (outs GPR:$Rn), (ins imm8:$imm, GPR:$src),
                               "add #$imm,$Rn",
-                              [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
+                              [(set i32:$Rn, (add imm8:$imm, i32:$src))]>;
 
   // addc Rm, Rn
-  let Defs = [SR], Uses = [SR] in
+  let Defs = [SR], Uses = [SR], isCommutable = 1 in
   def ADDCRmRn      : InstRmRn<0b0011000000001110,
-                              (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "addc $Rm,$Rn",
-                              [(set i32:$Rn, (adde i32:$src, i32:$Rm))]>;
+                              [(set i32:$Rn, (adde i32:$Rm, i32:$src))]>;
   
   // addv Rm, Rn
-  let Defs = [SR] in
+  let Defs = [SR], isCommutable = 1 in
   def ADDVRmRn      : InstRmRn<0b0011000000001111,
-                              (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "addv $Rm,$Rn",
-                              [(set i32:$Rn, (addc i32:$src, i32:$Rm))]>;
+                              [(set i32:$Rn, (addc i32:$Rm, i32:$src))]>;
 
 }
 
@@ -543,23 +544,23 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 
   // sub Rm, Rn
   def SUBRmRn       : InstRmRn<0b0011000000001000,
-                              (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "sub $Rm,$Rn",
-                              [(set i32:$Rn, (sub i32:$src, i32:$Rm))]>;
+                              [(set i32:$Rn, (sub i32:$Rm, i32:$src))]>;
 
   // subc Rm, Rn
   let Defs = [SR], Uses = [SR] in
   def SUBCRmRn      : InstRmRn<0b0011000000001010,
-                              (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "subc $Rm,$Rn",
-                              [(set i32:$Rn, (sube i32:$src, i32:$Rm))]>;
+                              [(set i32:$Rn, (sube i32:$Rm, i32:$src))]>;
 
   // subv Rm, Rn
   let Defs = [SR] in
   def SUBVRmRn      : InstRmRn<0b0011000000001011,
-                              (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "subv $Rm,$Rn",
-                              [(set i32:$Rn, (subc i32:$src, i32:$Rm))]>;
+                              [(set i32:$Rn, (subc i32:$Rm, i32:$src))]>;
   
   // dt Rn
   let Defs = [SR] in
@@ -597,7 +598,7 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
   // mul.l Rm, Rn
   let Defs = [MACL] in
   def MULRmRn       : InstRmRn<0b0000000000000111, 
-                              (outs GPR:$Rn), (ins GPR:$src, GPR:$Rm),
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "mul.l $Rm,$Rn",
                               []>;
 
@@ -622,7 +623,7 @@ let hasSideEffects = 0, isCommutable = 1 in {
   // div0s Rm, Rn
   let Defs = [SR] in
   def DIV0SRmRn     : InstRmRn<0b0010000000000111, 
-                              (outs), (ins GPR:$Rn, GPR:$Rm),
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
                               "div0s $Rm,$Rn",
                               []>;
   
@@ -641,25 +642,6 @@ let hasSideEffects = 0, isCommutable = 1 in {
                               []>;
 }
 
-let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
-
-  // Expand LLVM sdiv to the following sequence:
-  // div0s
-  // div1 Rm, Rn
-  def DIVSRmRn        : SHPseudo<(outs GPR:$Rn), 
-                                 (ins GPR:$Rm, GPR:$src),
-                                 "; divs $Rm, $Rn",
-                                 [(set i32:$Rn, (sdiv i32:$Rm, i32:$src))]>;
-
-  // Expand LLVM udiv to the following sequence:
-  // div0u
-  // div1 Rm, Rn
-  def DIVURmRn        : SHPseudo<(outs GPR:$Rn), 
-                                 (ins GPR:$Rm, GPR:$src),
-                                 "; divu $Rm, $Rn",
-                                 [(set i32:$Rn, (udiv i32:$Rm, i32:$src))]>;
-}
-
 
 
 
@@ -742,6 +724,68 @@ def CMPSTRRmRn      : InstRmRn<0b0010000000001100,
 //===--------------------------------------------------------------------------===//
 
 
+let hasSideEffects = 0 in {
+
+  // and Rm,Rn
+  let Constraints = "$src = $Rn" in
+  def ANDRmRn       : InstRmRn<0b0010000000001001, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "and $Rm,$Rn",
+                              []>;
+  // and #imm,R0
+  let Defs = [R0], Uses = [R0] in
+  def ANDI8R0         : InstI8<0b1100100100000000, 
+                              (outs), (ins imm8:$imm),
+                              "and #$imm,R0",
+                              []>;
+
+  // not Rm,Rn
+  let Constraints = "$src = $Rn" in
+  def NOTRmRn       : InstRmRn<0b0110000000000111, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "not $Rm,$Rn",
+                              []>;
+
+  // or Rm,Rn
+  let Constraints = "$src = $Rn" in
+  def ORRmRn        : InstRmRn<0b0010000000001011, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "or $Rm,$Rn",
+                              []>;
+  // or #imm,R0
+  let Defs = [R0], Uses = [R0] in
+  def ORI8R0          : InstI8<0b1100101100000000, 
+                              (outs), (ins imm8:$imm),
+                              "or #$imm,R0",
+                              []>;
+
+  // xor Rm,Rn
+  let Constraints = "$src = $Rn" in
+  def XORRmRn       : InstRmRn<0b0010000000001010, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "xor $Rm,$Rn",
+                              []>;
+  // xor #imm,R0
+  let Defs = [R0], Uses = [R0] in
+  def XORI8R0         : InstI8<0b1100101000000000, 
+                              (outs), (ins imm8:$imm),
+                              "xor #$imm,R0",
+                              []>;
+
+  // tst Rm,Rn
+  let Defs = [SR], Constraints = "$src = $Rn" in
+  def TSTRmRn       : InstRmRn<0b0010000000001000, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "tst $Rm,$Rn",
+                              []>;
+  // tst #imm,R0
+  let Defs = [R0, SR], Uses = [R0] in
+  def TSTI8R0         : InstI8<0b1100100000000000, 
+                              (outs), (ins imm8:$imm),
+                              "tst #$imm,R0",
+                              []>;
+
+}
 
 
 
@@ -752,7 +796,102 @@ def CMPSTRRmRn      : InstRmRn<0b0010000000001100,
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
+let hasSideEffects = 0, Constraints = "$src = $Rn" in {
+
+  // rotcl Rn
+  let Defs = [SR] in
+  def ROTCLRn         : InstRn<0b0100000000100100, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "rotcl $Rn",
+                              []>;
+
+  // rotcr Rn
+  let Defs = [SR] in
+  def ROTCRRn         : InstRn<0b0100000000100101, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "rotcr $Rn",
+                              []>;
+
+  // rotl Rn
+  let Defs = [SR] in
+  def ROTLRn          : InstRn<0b0100000000000100, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "rotl $Rn",
+                              []>;
+
+  // rotr Rn
+  let Defs = [SR] in
+  def ROTRRn          : InstRn<0b0100000000000101, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "rotr $Rn",
+                              []>;
+
+  // shal Rn
+  let Defs = [SR] in
+  def SHALRn          : InstRn<0b0100000000100000, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shal $Rn",
+                              []>;
+
+  // shar Rn
+  let Defs = [SR] in
+  def SHARRn          : InstRn<0b0100000000100001, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shar $Rn",
+                              []>;
+
+  // shll Rn
+  let Defs = [SR] in
+  def SHLLRn          : InstRn<0b0100000000000000, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shll $Rn",
+                              []>;
+
+  // shll2 Rn
+  let Defs = [SR] in
+  def SHLL2Rn          : InstRn<0b0100000000001000, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shll2 $Rn",
+                              []>;
+
+  // shll8 Rn
+  def SHLL8Rn          : InstRn<0b0100000000011000, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shll8 $Rn",
+                              []>;
+
+  // shll16 Rn
+  def SHLL16Rn          : InstRn<0b0100000000101000, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shll16 $Rn",
+                              []>;
+
+  // shlr Rn
+  let Defs = [SR] in
+  def SHLRRn          : InstRn<0b0100000000000001, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shlr $Rn",
+                              []>;
+
+  // shlr2 Rn
+  def SHLR2Rn          : InstRn<0b0100000000001001, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shlr2 $Rn",
+                              []>;
+
+  // shlr8 Rn
+  def SHLR8Rn          : InstRn<0b0100000000011001, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shlr8 $Rn",
+                              []>;
+
+  // shlr16 Rn
+  def SHLR16Rn          : InstRn<0b0100000000101001, 
+                              (outs GPR:$Rn), (ins GPR:$src),
+                              "shlr16 $Rn",
+                              []>;
 
+}
 
 
 //===--------------------------------------------------------------------------===//
@@ -790,8 +929,8 @@ let isCall = 1 in {
 // Return Instructions
 //===--------------------------------------------------------------------------===//
 
-let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
-  def RTS             : Inst<0b0000000000001011,
+let isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1 in {
+  def RTS               : Inst<0b0000000000001011,
                               (outs), (ins),
                               "rts",
                               []>;
@@ -807,32 +946,229 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in {
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
+// clrmac
+def CLRMAC              : Inst<0b0000000000101000, (outs), (ins), "clrmac", []>;
+
+// clrt
+let Defs = [SR] in
+def CLRT                : Inst<0b0000000000001000, (outs), (ins), "clrt", []>;
+
+// ldc Rm, SR
+let Defs = [SR] in
+def LDCRmSR           : InstRm<0b0100000000001110, 
+                              (outs), (ins GPR:$Rm), 
+                              "ldc $Rm,SR",
+                              []>;
 
+// ldc.l @Rm+, SR
+let Defs = [SR] in
+def LDCLRminciSR      : InstRm<0b0100000000000111, 
+                              (outs), (ins GPR:$Rm), 
+                              "ldc.l @$Rm+,SR",
+                              []>;
 
+// ldc Rm, GBR
+let Defs = [GBR] in
+def LDCRmGBR          : InstRm<0b0100000000011110, 
+                              (outs), (ins GPR:$Rm), 
+                              "ldc $Rm,GBR",
+                              []>;
 
+// ldc.l @Rm+, GBR
+let Defs = [GBR] in
+def LDCLRminciGBR     : InstRm<0b0100000000010111, 
+                              (outs), (ins GPR:$Rm), 
+                              "ldc.l @$Rm+,GBR",
+                              []>;
 
-//===--------------------------------------------------------------------------===//
-// Control Instructions
-//===--------------------------------------------------------------------------===//
+// ldc Rm, VBR
+let Defs = [VBR] in
+def LDCRmVBR          : InstRm<0b0100000000101110, 
+                              (outs), (ins GPR:$Rm), 
+                              "ldc $Rm,VBR",
+                              []>;
+
+// ldc.l @Rm+, VBR
+let Defs = [VBR] in
+def LDCLRminciVBR     : InstRm<0b0100000000100111, 
+                              (outs), (ins GPR:$Rm), 
+                              "ldc.l @$Rm+,VBR",
+                              []>;
+
+// lds Rm, MACH
+let Defs = [MACH] in
+def LDSRmMACH         : InstRm<0b0100000000001010, 
+                              (outs), (ins GPR:$Rm), 
+                              "lds $Rm,MACH",
+                              []>;
+
+// lds.l @Rm+, MACH
+let Defs = [MACH] in
+def LDSLRminciMACH    : InstRm<0b0100000000000110, 
+                              (outs), (ins GPR:$Rm), 
+                              "lds.l @$Rm+,MACH",
+                              []>;
+
+// lds Rm, MACL
+let Defs = [MACH] in
+def LDSRmMACL         : InstRm<0b0100000000011010, 
+                              (outs), (ins GPR:$Rm), 
+                              "lds $Rm,MACL",
+                              []>;
+
+// lds.l @Rm+, MACL
+let Defs = [MACH] in
+def LDSLRminciMACL    : InstRm<0b0100000000010110, 
+                              (outs), (ins GPR:$Rm), 
+                              "lds.l @$Rm+,MACL",
+                              []>;
+
+// lds Rm, PR
+let Defs = [PR] in
+def LDSRmPR           : InstRm<0b0100000000101010, 
+                              (outs), (ins GPR:$Rm), 
+                              "lds $Rm,PR",
+                              []>;
+
+// lds.l @Rm+, PR
+let Defs = [PR] in
+def LDSLRminciPR      : InstRm<0b0100000000100110, 
+                              (outs), (ins GPR:$Rm), 
+                              "lds.l @$Rm+,PR",
+                              []>;
 
 // nop
 let hasSideEffects = 1 in
-def NOP : Inst<0b0000000000001001, (outs), (ins), "nop", []>;
+def NOP                 : Inst<0b0000000000001001, (outs), (ins), "nop", []>;
+
+// rte
+let isTerminator = 1, isReturn = 1, isBranch = 1, hasDelaySlot = 1 in
+def RTE                 : Inst<0b0000000000101011, (outs), (ins), "rte", []>;
+
+// sett
+let Defs = [SR] in
+def SETT                : Inst<0b0000000000011000, (outs), (ins), "sett", []>;
 
 // sleep
 let hasSideEffects = 1 in
-def SLEEP : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
+def SLEEP               : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
 
+// stc SR,Rn
+let Uses = [SR] in
+def STCSRRn           : InstRn<0b0000000000000010, 
+                              (outs GPR:$Rn), (ins), 
+                              "stc SR,$Rn",
+                              []>;
 
+// stc.l SR, at -Rn
+let Uses = [SR] in
+def STCLSRRndeci      : InstRn<0b0100000000000011, 
+                              (outs GPR:$Rn), (ins), 
+                              "stc.l SR, at -$Rn",
+                              []>;
+
+// stc GBR,Rn
+let Uses = [GBR] in
+def STCGBRRn          : InstRn<0b0000000000010010, 
+                              (outs GPR:$Rn), (ins), 
+                              "stc GBR,$Rn",
+                              []>;
+
+// stc.l GBR, at -Rn
+let Uses = [GBR] in
+def STCLGBRRndeci     : InstRn<0b0100000000010011, 
+                              (outs GPR:$Rn), (ins), 
+                              "stc.l GBR, at -$Rn",
+                              []>;
+
+// stc VBR,Rn
+let Uses = [VBR] in
+def STCVBRRn          : InstRn<0b0000000000100010, 
+                              (outs GPR:$Rn), (ins), 
+                              "stc VBR,$Rn",
+                              []>;
+
+// stc.l VBR, at -Rn
+let Uses = [VBR] in
+def STCLVBRRndeci     : InstRn<0b0100000000100011, 
+                              (outs GPR:$Rn), (ins), 
+                              "stc.l VBR, at -$Rn",
+                              []>;
+
+// sts MACH,Rn
+let Uses = [MACH] in
+def STSMACHRn         : InstRn<0b0000000000001010, 
+                              (outs GPR:$Rn), (ins), 
+                              "sts MACH,$Rn",
+                              []>;
+
+// sts.l MACH, at -Rn
+let Uses = [MACH] in
+def STSLMACHRndeci    : InstRn<0b0100000000000010, 
+                              (outs GPR:$Rn), (ins), 
+                              "sts.l MACH, at -$Rn",
+                              []>;
+
+// sts MACL,Rn
+let Uses = [MACL] in
+def STSMACLRn         : InstRn<0b0000000000011010, 
+                              (outs GPR:$Rn), (ins), 
+                              "sts MACL,$Rn",
+                              []>;
+
+// sts.l MACL, at -Rn
+let Uses = [MACL] in
+def STSLMACLRndeci    : InstRn<0b0100000000010010, 
+                              (outs GPR:$Rn), (ins), 
+                              "sts.l MACL, at -$Rn",
+                              []>;
+
+// sts PR,Rn
+let Uses = [PR] in
+def STSPRRn           : InstRn<0b0000000000101010, 
+                              (outs GPR:$Rn), (ins), 
+                              "sts PR,$Rn",
+                              []>;
+
+// sts.l PR, at -Rn
+let Uses = [PR] in
+def STSLPRRndeci      : InstRn<0b0100000000100010, 
+                              (outs GPR:$Rn), (ins), 
+                              "sts.l PR, at -$Rn",
+                              []>;
+
+// trapa #imm
+let Defs = [PC], isCall = 1 in
+def TRAPAI8           : InstI8<0b1100001100000000, 
+                              (outs), (ins imm8:$imm), 
+                              "trapa #$imm",
+                              []>;
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                                  Extensions
 //===--------------------------------------------------------------------------===//
-// Bigger Extensions
 //===--------------------------------------------------------------------------===//
 
 include "SuperHInstrDSP.td"
 
 
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                              Pseudo instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+
+
+
 //===--------------------------------------------------------------------------===//
-// Pseudo instructions
+// Stack Frame
 //===--------------------------------------------------------------------------===//
 
 // Helper instruction for mapping frame indices to relative frame pointer
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index a8781f921dcac..f6053dbb48798 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -19,6 +19,7 @@
 #include "SuperH.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/Support/Debug.h"
 
 using namespace llvm;
@@ -38,10 +39,6 @@ const TargetRegisterClass *SuperHRegisterInfo::getPointerRegClass(unsigned Kind)
   return &SH::GPRRegClass;
 }
 
-const TargetRegisterClass *SuperHRegisterInfo::intRegClass(unsigned Size) const {
-  return &SH::GPRRegClass;
-}
-
 const MCPhysReg *SuperHRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
   return CSR_SH_SaveList;
 }
@@ -50,15 +47,31 @@ const uint32_t *SuperHRegisterInfo::getCallPreservedMask(const MachineFunction &
   return CSR_SH_RegMask; 
 }
 
+const TargetRegisterClass *
+SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
+                                           const MachineFunction &MF) const {
+  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+
+  if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
+    return &SH::GPRRegClass;
+  }
+
+  if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
+    return &SH::GPRRegClass;
+  }
+
+  return TargetRegisterInfo::getLargestLegalSuperClass(RC, MF);
+}
+
 BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   BitVector Reserved(getNumRegs());
 
-  // R0 and R1 are always reserved as return slots.
+  // R0 is always reserved as some instructions can only write to it.
   Reserved.set(SH::R0);
-  Reserved.set(SH::R1);
 
-  // Also reserve the stack frame.
+  // Also reserve the stack frame and stack pointer.
   Reserved.set(SH::R14);
+  Reserved.set(SH::R15);
   return Reserved;
 }
 
@@ -95,4 +108,12 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
 
 Register SuperHRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
   return SH::R14;
+}
+
+Register SuperHRegisterInfo::getFrameRegister() const {
+  return SH::R14;
+}
+
+Register SuperHRegisterInfo::getStackRegister() const {
+  return SH::R15;
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index c5c6dbb88e2af..c40cffab52e7a 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -33,12 +33,16 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
   const uint32_t *getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const override;
   const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const override;
   BitVector getReservedRegs(const MachineFunction &MF) const override;
+  const TargetRegisterClass *getLargestLegalSuperClass(const TargetRegisterClass *RC,
+                                           const MachineFunction &MF) const override;
+  Register getFrameRegister(const MachineFunction &MF) const override;
   bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
                            unsigned FIOperandNum,
                            RegScavenger *RS = nullptr) const override;
 
-  Register getFrameRegister(const MachineFunction &MF) const override;
-  const TargetRegisterClass *intRegClass(unsigned Size) const;
+  // Helpers
+  Register getFrameRegister() const;
+  Register getStackRegister() const;
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index a1594fb811b08..f826f06f14337 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -151,13 +151,10 @@ let Namespace = "SH" in {
 // Register Classes
 //===----------------------------------------------------------------------===//
 
-def GPR : RegisterClass<"SH", [ i32 ], 32, (add
-  R0, R1, R2,  R3,  R4,  R5,  R6,  R7,  // Banked memory
-  R8, R9, R10, R11, R12, R13, R14, R15  // Non-banked memory.
-)>;
+def GPR : RegisterClass<"SH", [ i8, i16, i32 ], 32, (sequence "R%u", 0, 15)>;
 
 // 32-bit floating point registers.
-def FR32 : RegisterClass<"SH", [f32], 32, (add
+def FR32 : RegisterClass<"SH", [ f32 ], 32, (add
   // FR
   FR0,  FR1,  FR2,  FR3,  FR4,  FR5,  FR6,  FR7,
   FR8,  FR9, FR10, FR11, FR12, FR13, FR14, FR15,
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 27a5bf798a5a5..09befc32c7ead 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -39,6 +39,7 @@ class SuperHPassConfig : public TargetPassConfig {
     : TargetPassConfig(TM, PM) {}
 
   bool addInstSelector() override;
+  void addPreSched2() override;
   SuperHTargetMachine &getSuperHTargetMachine() const {
     return getTM<SuperHTargetMachine>();
   }
@@ -48,6 +49,11 @@ bool SuperHPassConfig::addInstSelector() {
   addPass(createSuperHISelDag(getSuperHTargetMachine(), getOptLevel()));
   return false;
 }
+
+void SuperHPassConfig::addPreSched2() {
+  addPass(createSuperHFillDelaySlotsPass());
+}
+
 } // namespace
 
 

>From 089b94a84f4bfcee1947595b3f438bd677fd22d6 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 10 Aug 2026 10:02:03 +0200
Subject: [PATCH 18/67] Move canFillDelaySlot to InstrInfo

---
 .../Target/SuperH/SuperHFillDelaySlots.cpp    |  9 ++----
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 30 -------------------
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 26 +++++++---------
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |  6 +---
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  4 +--
 5 files changed, 15 insertions(+), 60 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index f96038e3b9cb7..76dc6ff0eed2b 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -44,7 +44,7 @@ class SuperHFillDelaySlots : public MachineFunctionPass {
   typedef Block::iterator BlockIt;
 
   const SuperHRegisterInfo *TRI;
-  const TargetInstrInfo *TII;
+  const SuperHInstrInfo *TII;
 
   bool hasDelaySlot(MachineInstr &I);
   bool expandMBB(Block &MBB);
@@ -63,12 +63,7 @@ bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
 
     // If the prior instruction does not have a delay slot
     // we swap the instructions.
-    //
-    // NOTE:  SuperH does not allow branch instructions
-    //        of any kind to be situated in a delay slot.
-    //        as such we fall through to the NOP in that
-    //        instance.
-    if (!Prev->isBranch() && !Prev->hasDelaySlot()) {
+    if (TII->canFillDelaySlot(Prev->getOpcode())) {
       LDBG() << "Swapping " << TII->getName(MI.getOpcode()) 
              << " and " << TII->getName(Prev->getOpcode()) 
              << " @ " << MBB.getParent()->getName();
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 5c5f851ec4a72..badd48f1df62a 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -96,34 +96,6 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValu
 //                             Branch Lowering
 //===----------------------------------------------------------------------===//
 
-// Due to delay slots there needs to be a bit more smarts
-// in here.
-bool SuperHDAGToDAGISel::trySelectRET(SDNode *N) {
-  SDValue Chain = N->getOperand(0);
-  unsigned LastOpNum = N->getNumOperands() - 1;
-
-  // Skip the incoming flag if present
-  if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
-    --LastOpNum;
-  }
-
-  SDLoc DL(N);
-  SmallVector<SDValue, 8> Ops;
-
-  // RTS implicitly depends on the R0 register for
-  // return values.
-  Ops.push_back(CurDAG->getRegister(SH::R0, MVT::i32));
-  Ops.push_back(Chain);
-  Ops.push_back(Chain.getValue(1));
-
-  SDNode *ResNode = CurDAG->getMachineNode(SH::RTS, DL, MVT::Other, Ops);
-  //ResNode = CurDAG->getMachineNode(SH::NOP, DL, MVT::Other, SDValue(ResNode, 0));
-
-  ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
-  CurDAG->RemoveDeadNode(N);
-  return true;
-}
-
 bool SuperHDAGToDAGISel::trySelectFrameIndex(SDNode *N) {
   auto DL = CurDAG->getDataLayout();
 
@@ -140,8 +112,6 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
   switch(Opcode) {
   case ISD::FrameIndex:
     return trySelectFrameIndex(N);
-  case SHISD::RET_GLUE:
-    return trySelectRET(N);
   default:
     return false;
   }
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 8489d91f8ac85..551e469a9b354 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -52,20 +52,14 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   llvm_unreachable("Impossible reg-to-reg copy");
 }
 
-bool SuperHInstrInfo::expandRET(MachineInstr &MI) const {
-  MachineBasicBlock &MBB = *MI.getParent();
-  MachineBasicBlock::iterator MBBI = MI.getIterator();
-  DebugLoc DL = MI.getDebugLoc();
-
-
-  BuildMI(MBB, MBBI, DL, get(SH::NOP));
-  return true;
-}
-
-bool SuperHInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
-  switch(MI.getOpcode()) {
-  case SH::RTS:
-    return expandRET(MI);
-  }
-  return false;
+// Gets whether a given opcode can fill a delay slot.
+// 
+// SuperH does not allow branch instructions of any kind to be situated 
+// in a delay slot, nor does it allow instructions with delay slots
+// to be chained together.
+bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
+  auto Desc = this->get(Opcode);
+  return !Desc.hasDelaySlot() && 
+         !Desc.isBranch() && 
+         !Desc.isCall() && !Desc.isReturn();
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index bbd95d0148c89..78e9d10ae445c 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -41,11 +41,7 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
                            bool RenamableDest = false,
                            bool RenamableSrc = false) const override;
 
-  bool expandPostRAPseudo(MachineInstr &MI) const override;
-
-private:
-  // Custom expansions
-  bool expandRET(MachineInstr &MI) const;
+  bool canFillDelaySlot(unsigned Opcode) const;
 };
 
 const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 32f27707ddf78..7ebddb4759fc9 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -916,7 +916,7 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
 // Call Instructions
 //===--------------------------------------------------------------------------===//
 
-let isCall = 1 in {
+let isCall = 1, hasDelaySlot = 1 in {
   let Uses = [GBR] in
   def JSRRmi          : InstRm<0b0100000000001011,
                               (outs), (ins GPRMem:$Rm),
@@ -933,7 +933,7 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1 in {
   def RTS               : Inst<0b0000000000001011,
                               (outs), (ins),
                               "rts",
-                              []>;
+                              [(SHRetGlue)]>;
 }
 
 

>From 0852eda181e7f44004f606f272e98ed077aac113 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 10 Aug 2026 10:04:24 +0200
Subject: [PATCH 19/67] Fix comment

---
 llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 76dc6ff0eed2b..9f7bacb1c92b5 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -61,8 +61,8 @@ bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
   MachineInstr &MI = *MBBI;
   if (auto *Prev = MBBI->getPrevNode()) {
 
-    // If the prior instruction does not have a delay slot
-    // we swap the instructions.
+    // If the prior instruction is capable of filling the delay slot
+    // swap the 2 instructions.
     if (TII->canFillDelaySlot(Prev->getOpcode())) {
       LDBG() << "Swapping " << TII->getName(MI.getOpcode()) 
              << " and " << TII->getName(Prev->getOpcode()) 

>From c9c1444bab4fe473acb24559e7c3f577b24ab2e6 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 10 Aug 2026 11:50:23 +0200
Subject: [PATCH 20/67] Add isDelayIllegal TSFlag

---
 .../lib/Target/SuperH/SuperHFrameLowering.cpp | 12 +++++++---
 llvm/lib/Target/SuperH/SuperHInstrFormats.td  |  4 ++++
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  3 ++-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 24 +++++++++----------
 4 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 5db9816b1ca2d..4d11c6e99983c 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -40,11 +40,15 @@ static unsigned getShiftAmt(uint32_t Val) {
 }
 
 // Helper to emit stack pointer adjustment.
-static void emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasicBlock::iterator MBBI, int32_t AdjValue) {
+static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasicBlock::iterator MBBI, int32_t AdjValue) {
   DebugLoc dl;
   const SuperHInstrInfo &TII = *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
   const SuperHRegisterInfo &RII = *static_cast<const SuperHRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
   MachineInstr::MIFlag MFlag = AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
+  
+  // No stack frame allocation neccesary.
+  if (AdjValue == 0)
+    return false;
 
   Register SP = RII.getStackRegister();
 
@@ -56,7 +60,7 @@ static void emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
       .addImm((int)AdjValue)
       .addReg(SP);
 
-    return;
+    return true;
   }
 
   // Slow path, shift 8 bits at a time into r0.
@@ -93,6 +97,7 @@ static void emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
     .addReg(SH::R0, RegState::Kill)
     .addReg(SP)
     .setMIFlag(MFlag);
+  return true;
 }
 
 void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
@@ -162,7 +167,8 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
     .setMIFlag(MachineInstr::FrameDestroy);
 
   // 3. Delete stack frame, restoring stack pointer.
-  emitSPAdj(MF, MBB, MBBI, StackSize);
+  if (StackSize > 0)
+    emitSPAdj(MF, MBB, MBBI, StackSize);
 }
 
 MachineBasicBlock::iterator
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index df62cf6e9cfc4..1c2e6e03f6b3c 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -45,6 +45,10 @@ class SHInst<dag outs, dag ins, string asmstr, list<dag> pattern = []>
   dag InOperandList = ins;
   let AsmString = asmstr;
   let Pattern = pattern;
+
+  // Whether the instruction is incompatible with delay slots.
+  bit isDelayIllegal = 0;
+  let TSFlags{0} = isDelayIllegal;
 }
 
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 551e469a9b354..b5015c9e8dc63 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -61,5 +61,6 @@ bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
   auto Desc = this->get(Opcode);
   return !Desc.hasDelaySlot() && 
          !Desc.isBranch() && 
-         !Desc.isCall() && !Desc.isReturn();
+         !Desc.isCall() && !Desc.isReturn() &&
+         !(Desc.TSFlags & 0x1);
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 7ebddb4759fc9..3d7303b507dbd 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -229,21 +229,21 @@ def MOVI8Rn       : InstRnI8<0b1110000000000000,
                             [(set i32:$Rn, imm8:$imm)]>;
 
 // mov @(disp, PC), R0
-let hasSideEffects = 0, mayLoad = 1, Defs = [R0] in
+let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
 def MOVAD8PCR0      : InstD8<0b1100011100000000,
                             (outs), (ins disp8:$disp),
                             "mov @($disp,PC),R0",
                             []>;
 
 // mov.w @(disp,PC), Rn 
-let hasSideEffects = 0, mayLoad = 1 in
+let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
 def MOVWD8PCRn    : InstRnD8<0b1001000000000000,
                             (outs GPR:$Rn), (ins disp8:$disp),
                             "mov.w @($disp,PC),$Rn",
                             [(set i32:$Rn, (sextloadi16 addr:$disp))]>;
 
 // mov.l @(disp,PC), Rn 
-let hasSideEffects = 0, mayLoad = 1 in
+let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
 def MOVLD8PCRn    : InstRnD8<0b1101000000000000,
                             (outs GPR:$Rn), (ins disp8:$disp),
                             "mov.l @($disp,PC),$Rn",
@@ -954,14 +954,14 @@ let Defs = [SR] in
 def CLRT                : Inst<0b0000000000001000, (outs), (ins), "clrt", []>;
 
 // ldc Rm, SR
-let Defs = [SR] in
+let Defs = [SR], isDelayIllegal = 1 in
 def LDCRmSR           : InstRm<0b0100000000001110, 
                               (outs), (ins GPR:$Rm), 
                               "ldc $Rm,SR",
                               []>;
 
 // ldc.l @Rm+, SR
-let Defs = [SR] in
+let Defs = [SR], isDelayIllegal = 1 in
 def LDCLRminciSR      : InstRm<0b0100000000000111, 
                               (outs), (ins GPR:$Rm), 
                               "ldc.l @$Rm+,SR",
@@ -982,14 +982,14 @@ def LDCLRminciGBR     : InstRm<0b0100000000010111,
                               []>;
 
 // ldc Rm, VBR
-let Defs = [VBR] in
+let Defs = [VBR], isDelayIllegal = 1 in
 def LDCRmVBR          : InstRm<0b0100000000101110, 
                               (outs), (ins GPR:$Rm), 
                               "ldc $Rm,VBR",
                               []>;
 
 // ldc.l @Rm+, VBR
-let Defs = [VBR] in
+let Defs = [VBR], isDelayIllegal = 1 in
 def LDCLRminciVBR     : InstRm<0b0100000000100111, 
                               (outs), (ins GPR:$Rm), 
                               "ldc.l @$Rm+,VBR",
@@ -1050,18 +1050,18 @@ let Defs = [SR] in
 def SETT                : Inst<0b0000000000011000, (outs), (ins), "sett", []>;
 
 // sleep
-let hasSideEffects = 1 in
+let hasSideEffects = 1, isDelayIllegal = 1 in
 def SLEEP               : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
 
 // stc SR,Rn
-let Uses = [SR] in
+let Uses = [SR], isDelayIllegal = 1 in
 def STCSRRn           : InstRn<0b0000000000000010, 
                               (outs GPR:$Rn), (ins), 
                               "stc SR,$Rn",
                               []>;
 
 // stc.l SR, at -Rn
-let Uses = [SR] in
+let Uses = [SR], isDelayIllegal = 1 in
 def STCLSRRndeci      : InstRn<0b0100000000000011, 
                               (outs GPR:$Rn), (ins), 
                               "stc.l SR, at -$Rn",
@@ -1082,14 +1082,14 @@ def STCLGBRRndeci     : InstRn<0b0100000000010011,
                               []>;
 
 // stc VBR,Rn
-let Uses = [VBR] in
+let Uses = [VBR], isDelayIllegal = 1 in
 def STCVBRRn          : InstRn<0b0000000000100010, 
                               (outs GPR:$Rn), (ins), 
                               "stc VBR,$Rn",
                               []>;
 
 // stc.l VBR, at -Rn
-let Uses = [VBR] in
+let Uses = [VBR], isDelayIllegal = 1 in
 def STCLVBRRndeci     : InstRn<0b0100000000100011, 
                               (outs GPR:$Rn), (ins), 
                               "stc.l VBR, at -$Rn",

>From 63ea49e635318407397cc499e9ba46bd5c27a5f4 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 21 Aug 2026 22:47:56 +0200
Subject: [PATCH 21/67] Further SuperH instruction lowering

---
 clang/include/clang/Options/Options.td        |   19 +
 .../llvm/BinaryFormat/ELFRelocs/SuperH.def    |    2 +-
 llvm/lib/Target/SuperH/CMakeLists.txt         |   10 +-
 .../SuperH/MCTargetDesc/SuperHAsmBackend.cpp  |   12 +-
 .../SuperH/MCTargetDesc/SuperHBaseInfo.h      |  143 ++
 .../MCTargetDesc/SuperHELFObjectWriter.cpp    |  129 +-
 .../SuperH/MCTargetDesc/SuperHFixupKinds.h    |    2 +-
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |   55 +-
 .../SuperH/MCTargetDesc/SuperHInstPrinter.h   |    2 +
 .../SuperH/MCTargetDesc/SuperHMCAsmInfo.h     |   17 +-
 .../MCTargetDesc/SuperHMCCodeEmitter.cpp      |   42 +-
 .../MCTargetDesc/SuperHTargetStreamer.cpp     |    3 +-
 llvm/lib/Target/SuperH/SuperH.h               |    2 +
 llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp   |  198 ++-
 .../Target/SuperH/SuperHBasicBlockInfo.cpp    |  110 ++
 llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h |  157 +++
 .../SuperH/SuperHConstantIslandPass.cpp       | 1184 +++++++++++++++++
 .../Target/SuperH/SuperHConstantPoolValue.cpp |  223 ++++
 .../Target/SuperH/SuperHConstantPoolValue.h   |  212 +++
 .../Target/SuperH/SuperHFillDelaySlots.cpp    |   80 +-
 .../lib/Target/SuperH/SuperHFrameLowering.cpp |  170 ++-
 llvm/lib/Target/SuperH/SuperHFrameLowering.h  |    9 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  239 +++-
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp |  226 +++-
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |   40 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  201 ++-
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |   42 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  301 +++--
 llvm/lib/Target/SuperH/SuperHMCInstLower.cpp  |   34 +-
 .../SuperH/SuperHMachineFunctionInfo.cpp      |  126 ++
 .../Target/SuperH/SuperHMachineFunctionInfo.h |   68 +
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp |   10 +-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.h   |    1 +
 llvm/lib/Target/SuperH/SuperHSubtarget.cpp    |  116 +-
 llvm/lib/Target/SuperH/SuperHSubtarget.h      |   51 +-
 .../lib/Target/SuperH/SuperHTargetMachine.cpp |   31 +
 llvm/lib/Target/SuperH/SuperHTargetMachine.h  |    4 +
 37 files changed, 3959 insertions(+), 312 deletions(-)
 create mode 100644 llvm/lib/Target/SuperH/MCTargetDesc/SuperHBaseInfo.h
 create mode 100644 llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
 create mode 100644 llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
 create mode 100644 llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
 create mode 100644 llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
 create mode 100644 llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
 create mode 100644 llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
 create mode 100644 llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h

diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 06461acdf216e..29d5ba2b97a75 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -219,6 +219,8 @@ def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
                                Group<m_Group>, DocName<"Hexagon">;
 def m_sparc_Features_Group : OptionGroup<"<sparc features group>">,
                                Group<m_Group>, DocName<"SPARC">;
+def m_superh_Features_Group : OptionGroup<"<superh features group>">,
+                               Group<m_Group>, DocName<"SuperH">;
 // The features added by this group will not be added to target features.
 // These are explicitly handled.
 def m_hexagon_Features_HVX_Group : OptionGroup<"<hexagon features group>">,
@@ -7334,6 +7336,23 @@ foreach i = 0 ... 5 in
     HelpText<"Reserve the I"#i#" register (SPARC only)">;
 } // let Flags = [TargetSpecific]
 
+// SuperH feature flags
+let Flags = [TargetSpecific] in {
+  def maccumulate_outgoing_args : Flag<["-"], "maccumulate-outgoing-args">, 
+    Group<m_superh_Features_Group>,
+    HelpText<"Reserve space for outgoing arguments in the function prologue. (SuperH only)">;
+  def mcbranch_force_delay_slot : Flag<["-"], "mcbranch-force-delay-slot">, 
+    Group<m_superh_Features_Group>,
+    HelpText<"Force the usage of delay slots for conditional branches. (SuperH only)">;
+  def mfsca : Flag<["-"], "mfsca">, Group<m_superh_Features_Group>,
+    HelpText<"Enable the use of the fsca instruction. (SuperH only)">;
+  def mfsrra : Flag<["-"], "mfsrra">, Group<m_superh_Features_Group>,
+    HelpText<"Enable the use of the fsrra instruction. (SuperH only)">;
+  def mzdcbranch : Flag<["-"], "mzdcbranch">, 
+    Group<m_superh_Features_Group>,
+    HelpText<"Assume that zero displacement conditional branches are fast. (SuperH only)">;
+} // let Flags = [TargetSpecific]
+
 // M68k features flags
 let Flags = [TargetSpecific] in {
 def m68000 : Flag<["-"], "m68000">, Group<m_m68k_Features_Group>;
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
index 943ae7dd39440..2db8a2d5c4938 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/SuperH.def
@@ -30,7 +30,7 @@ ELF_RELOC(R_SH_GOTPLT10BY4,         189)
 ELF_RELOC(R_SH_GOTPLT10BY8,         191)
 ELF_RELOC(R_SH_GOTOFF,              166)
 ELF_RELOC(R_SH_GOTOFF_LOW16,        181)
-ELF_RELOC(R_SH_GOTOFF_MEWLOW16,     182)
+ELF_RELOC(R_SH_GOTOFF_MEDLOW16,     182)
 ELF_RELOC(R_SH_GOTOFF_MEDHI16,      183)
 ELF_RELOC(R_SH_GOTOFF_HI16,         184)
 ELF_RELOC(R_SH_GOTPC,               167)
diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index a67293ce502f4..a09955850e10a 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -19,15 +19,19 @@ add_public_tablegen_target(SuperHCommonTableGen)
 add_llvm_target(SuperHCodeGen
   SuperHTargetMachine.cpp
   SuperHFrameLowering.cpp
+  SuperHConstantPoolValue.cpp
+  SuperHBasicBlockInfo.cpp
+  SuperHMachineFunctionInfo.cpp
   SuperHRegisterInfo.cpp
-  SuperHMCInstLower.cpp
+  SuperHInstrInfo.cpp
   SuperHSelectionDAGInfo.cpp
-  SuperHISelDAGToDAG.cpp
   SuperHISelLowering.cpp
+  SuperHISelDAGToDAG.cpp
+  SuperHMCInstLower.cpp
   SuperHAsmPrinter.cpp
-  SuperHInstrInfo.cpp
   SuperHSubtarget.cpp
   SuperHFillDelaySlots.cpp
+  SuperHConstantIslandPass.cpp
 
   LINK_COMPONENTS
   Analysis
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 26bfcbbca5b03..ae24d50d921b8 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -41,14 +41,14 @@ SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) :
 
 bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
                     const MCSubtargetInfo *STI) const {
-  const uint16_t SH_NopEnc = 0b0000000000001001;
+  const uint16_t SHNopEnc = 0b0000000000001001;
 
   // If the count is not 4-byte aligned, we must be writing data into the
   // text section (otherwise we have unaligned instructions, and thus have
   // far bigger problems), so just write NOP instructions.
   uint64_t NumNops = Count / 2;
   for (uint64_t i = 0; i != NumNops; ++i)
-    support::endian::write(OS, SH_NopEnc, Endian);
+    support::endian::write(OS, SHNopEnc, Endian);
 
   // Write any straggling zeros needed.
   OS.write_zeros(Count & 1);
@@ -70,7 +70,7 @@ std::optional<MCFixupKind> SuperHAsmBackend::getFixupKind(StringRef Name) const
 
 MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
   // clang-format off
-  const static MCFixupKindInfo Infos[SuperH::NumTargetFixupKinds] = {
+  const static MCFixupKindInfo Infos[SH::NumTargetFixupKinds] = {
       // This table *must* be in same the order of fixup_* kinds in
       // SuperHFixupKinds.h.
       //
@@ -123,7 +123,7 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
   if (Kind < FirstTargetFixupKind)
     return MCAsmBackend::getFixupKindInfo(Kind);
 
-  assert(unsigned(Kind - FirstTargetFixupKind) < SuperH::NumTargetFixupKinds &&
+  assert(unsigned(Kind - FirstTargetFixupKind) < SH::NumTargetFixupKinds &&
          "Invalid kind!");
 
   return Infos[Kind - FirstTargetFixupKind];
@@ -171,8 +171,10 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
   default: 
     return {};
 
+  case FK_Data_1:
   case FK_Data_2:
-  case FK_Data_4: {
+  case FK_Data_4:
+  case FK_Data_8: {
     const auto *EValue = Fixup.getValue();
     if (!EValue->evaluateAsRelocatable(PCITarget, Asm))
       return true;
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHBaseInfo.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHBaseInfo.h
new file mode 100644
index 0000000000000..f0f7b7e51c847
--- /dev/null
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHBaseInfo.h
@@ -0,0 +1,143 @@
+//===-- SuperHBaseInfo.h - Top level definitions for SH MC --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===------------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains small standalone helper functions and enum definitions
+/// for the SuperH target useful for the compiler back-end and the MC
+/// libraries.  As such, it deliberately does not include references to LLVM
+/// core code gen types, passes, etc..
+///
+//===------------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHBASEINFO_H
+#define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHBASEINFO_H
+
+#include "SuperHMCTargetDesc.h"
+
+#include "llvm/MC/MCExpr.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#define GET_INSTRINFO_MI_OPS_INFO
+#define GET_INSTRINFO_OPERAND_TYPES_ENUM
+#define GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP
+#include "SuperHGenInstrInfo.inc"
+
+namespace llvm {
+
+namespace SHII {
+/// Target Operand Flag enum.
+enum TOF {
+
+  MO_NO_FLAG,
+
+  /// On a symbol operand this indicates that the immediate is the absolute
+  /// address of the symbol.
+  MO_DIR,
+
+  /// On a symbol operand this indicates that the immediate is the pc-relative
+  /// address of the symbol.
+  MO_PCREL,
+
+  /// On a symbol operand this indicates that the immediate is the offset to
+  /// the GOT entry for the symbol name from the base of the GOT.
+  ///
+  ///    name at GOT
+  MO_GOT,
+
+  /// On a symbol operand this indicates that the immediate is the offset to
+  /// the location of the symbol name from the base of the GOT.
+  ///
+  ///    name at GOTOFF
+  MO_GOTOFF,
+
+  /// On a symbol operand this indicates that the immediate is offset to the
+  /// PLT entry of symbol name from the current code location.
+  ///
+  ///    name at PLT
+  MO_PLT,
+
+  /// On a symbol operand this indicates that the immediate is offset to the
+  /// location of the symbol name from the base of the GOT added to the storage
+  /// unit.
+  ///
+  ///    name at GOTPLT
+  MO_GOTPLT,
+
+  /// On a symbol operand this indicates that the immediate is offset to the
+  /// GOT entry for the symbol name from the current code location.
+  ///
+  ///    name at GOTPC
+  MO_GOTPC,
+
+}; // enum TOF
+
+/// Return true if the specified TargetFlag operand is a reference to a stub
+/// for a global, not the global itself.
+inline static bool isGlobalStubReference(unsigned char TargetFlag) {
+  switch (TargetFlag) {
+  default:
+    return false;
+  case SHII::MO_GOTPC: // pc-relative GOT reference.
+  case SHII::MO_GOT:   // normal GOT reference.
+    return true;
+  }
+}
+
+/// Return True if the specified GlobalValue is a direct reference for a
+/// symbol.
+inline static bool isDirectGlobalReference(unsigned char Flag) {
+  switch (Flag) {
+  default:
+    return false;
+  case SHII::MO_NO_FLAG:
+  case SHII::MO_DIR:
+  case SHII::MO_PCREL:
+    return true;
+  }
+}
+
+/// Return true if the specified global value reference is relative to a 32-bit
+/// PIC base (M68kISD::GLOBAL_BASE_REG). If this is true, the addressing mode
+/// has the PIC base register added in.
+inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
+  switch (TargetFlag) {
+  default:
+    return false;
+  case SHII::MO_GOTOFF: // isPICStyleGOT: local global.
+  case SHII::MO_GOT:    // isPICStyleGOT: other global.
+    return true;
+  }
+}
+
+/// Return True if the specified GlobalValue requires PC addressing mode.
+inline static bool isPCRelGlobalReference(unsigned char Flag) {
+  switch (Flag) {
+  default:
+    return false;
+  case SHII::MO_GOTPC:
+  case SHII::MO_PCREL:
+    return true;
+  }
+}
+
+/// Return True if the Block is referenced using PC
+inline static bool isPCRelBlockReference(unsigned char Flag) {
+  switch (Flag) {
+  default:
+    return false;
+  case SHII::MO_PCREL:
+    return true;
+  }
+}
+
+} // namespace SHII
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index 0e337f12d546a..20c6718e399ce 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -7,6 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
+#include "MCTargetDesc/SuperHFixupKinds.h"
+#include "SuperHMCAsmInfo.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCELFObjectWriter.h"
@@ -19,6 +22,8 @@
 
 using namespace llvm;
 
+#define DEBUG_TYPE "sh-elf-objwriter"
+
 namespace llvm {
   class SuperHELFObjectWriter : public MCELFObjectTargetWriter {
   public:
@@ -41,12 +46,128 @@ namespace llvm {
 unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
                                             const MCValue &Target,
                                             bool IsPCRel) const {
-  auto Kind = Fixup.getKind();
-  uint8_t Specifier = Target.getSpecifier();
-  if (Kind == FK_Data_4 || Kind == FK_Data_2)
+  auto Spec = Target.getSpecifier();
+  switch ((unsigned)Fixup.getKind()) { 
+  case FK_Data_1:
+  case FK_Data_2:
+  case FK_Data_4:
+  case FK_Data_8:
     return ELF::R_SH_NONE;
 
-  return Specifier;
+  case SH::fixup_got32:
+    return ELF::R_SH_GOT32;
+
+  case SH::fixup_got_low16:
+    return ELF::R_SH_GOT_LOW16;
+
+  case SH::fixup_got_medlow16:
+    return ELF::R_SH_GOT_MEDLOW16;
+
+  case SH::fixup_got_medhi16:
+    return ELF::R_SH_GOT_MEDHI16;;
+
+  case SH::fixup_got_hi16:
+    return ELF::R_SH_GOT_HI16;
+
+  case SH::fixup_plt32:
+    return ELF::R_SH_PLT32;
+
+  case SH::fixup_plt_low16:
+    return ELF::R_SH_PLT_LOW16;
+
+  case SH::fixup_plt_medlow16:
+    return ELF::R_SH_PLT_MEDLOW16;
+
+  case SH::fixup_plt_medhi16:
+    return ELF::R_SH_PLT_MEDHI16;;
+
+  case SH::fixup_plt_hi16:
+    return ELF::R_SH_PLT_HI16;
+
+  case SH::fixup_gotplt32:
+    return ELF::R_SH_GOTPLT32;
+
+  case SH::fixup_gotplt_low16:
+    return ELF::R_SH_GOTPLT_LOW16;
+
+  case SH::fixup_gotplt_medlow16:
+    return ELF::R_SH_GOTPLT_MEDLOW16;
+
+  case SH::fixup_gotplt_medhi16:
+    return ELF::R_SH_GOTPLT_MEDHI16;;
+
+  case SH::fixup_gotplt_hi16:
+    return ELF::R_SH_GOTPLT_HI16;
+
+  case SH::fixup_gotoff:
+    return ELF::R_SH_GOTOFF;
+
+  case SH::fixup_gotoff_low16:
+    return ELF::R_SH_GOTOFF_LOW16;
+
+  case SH::fixup_gotoff_medlow16:
+    return ELF::R_SH_GOTOFF_MEDLOW16;
+
+  case SH::fixup_gotoff_medhi16:
+    return ELF::R_SH_GOTOFF_MEDHI16;;
+
+  case SH::fixup_gotoff_hi16:
+    return ELF::R_SH_GOTOFF_HI16;
+
+  case SH::fixup_gotpc:
+    return ELF::R_SH_GOTPC;
+
+  case SH::fixup_gotpc_low16:
+    return ELF::R_SH_GOTPC_LOW16;
+
+  case SH::fixup_gotpc_medlow16:
+    return ELF::R_SH_GOTPC_MEDLOW16;
+
+  case SH::fixup_gotpc_medhi16:
+    return ELF::R_SH_GOTPC_MEDHI16;;
+
+  case SH::fixup_gotpc_hi16:
+    return ELF::R_SH_GOTPC_HI16;
+
+  case SH::fixup_copy:
+    return ELF::R_SH_COPY;
+
+  case SH::fixup_copy64:
+    return ELF::R_SH_COPY64;
+
+  case SH::fixup_glob_dat:
+    return ELF::R_SH_GLOB_DAT;
+
+  case SH::fixup_glob_dat64:
+    return ELF::R_SH_GLOB_DAT64;
+
+  case SH::fixup_jump_slot:
+    return ELF::R_SH_JMP_SLOT;
+
+  case SH::fixup_jump_slot64:
+    return ELF::R_SH_JMP_SLOT64;
+
+  case SH::fixup_relative:
+    return ELF::R_SH_RELATIVE;
+
+  case SH::fixup_relative64:
+    return ELF::R_SH_RELATIVE64;
+
+  case SH::fixup_dir32:
+    return ELF::R_SH_DIR32;
+
+  case SH::fixup_rel32:
+    return ELF::R_SH_REL32;
+
+  case SH::fixup_64:
+    return ELF::R_SH_64;
+
+  case SH::fixup_64_pcrel:
+    return ELF::R_SH_64_PCREL;
+
+  default:
+    llvm_unreachable("invalid fixup kind!");
+  }
 }
 
 bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
index ee8865c44bb26..821a588c3dd44 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
@@ -12,7 +12,7 @@
 #include "llvm/MC/MCFixup.h"
 
 namespace llvm {
-namespace SuperH {
+namespace SH {
 
 // clang-format off
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 987b0594cf813..fadac2158f630 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -25,9 +25,9 @@ using namespace llvm;
 // The generated AsmMatcher SparcGenAsmWriter uses "SuperH" as the target
 // namespace. But SuperH backend uses "SH" as its namespace.
 namespace llvm {
-	namespace SuperH {
-	  using namespace SH;
-	}
+  namespace SuperH {
+    using namespace SH;
+  }
 }
 
 #define GET_INSTRUCTION_NAME
@@ -38,33 +38,42 @@ SuperHInstPrinter::SuperHInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MI
                     const MCRegisterInfo &MRI) : MCInstPrinter(MAI, MII, MRI) {}
 
 void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
-	OS << StringRef(getRegisterName(Reg)).lower();
+  OS << StringRef(getRegisterName(Reg)).lower();
+}
+
+void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address, 
+        unsigned OpNo, raw_ostream &O) {
+  printOperand(MI, OpNo, O);
+}
+
+void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
+  printOperand(MI, OpNo, O);
 }
 
 void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
-	const MCOperand &Op = MI->getOperand(OpNo);
-	
-    // Print Register
-	if (Op.isReg()) {
-		printRegName(O, Op.getReg());
-		return;
-	}
+  const MCOperand &Op = MI->getOperand(OpNo);
+  
+
+  // Print Register
+  if (Op.isReg()) {
+    printRegName(O, Op.getReg());
+    return;
+  }
 
-	// Print immediates
-	if (Op.isImm()) {
-		O << Op.getImm();
-		return;
-	}
+  // Print immediates
+  if (Op.isImm()) {
+    O << Op.getImm();
+    return;
+  }
 
-	// Print symbol references
-	if (Op.isBareSymbolRef()) {
-		const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
-		O << SymOp->getSymbol().getName();
-		return;
-	}
+  // Print symbol references
+  if (const MCSymbolRefExpr *SymOp = dyn_cast_or_null<MCSymbolRefExpr>(Op.getExpr())) {
+    O << SymOp->getSymbol().getName();
+    return;
+  }
 }
 
 void SuperHInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
                  const MCSubtargetInfo &STI, raw_ostream &OS) {
-	printInstruction(MI, Address, OS);
+  printInstruction(MI, Address, OS);
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index ebdaca0d64915..f22b48ac733b8 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -47,6 +47,8 @@ class SuperHInstPrinter : public MCInstPrinter {
 
 private:
   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
index 25cd78f53becc..0dfc47b66f766 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
@@ -16,6 +16,7 @@
 #define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCASMINFO_H
 
 #include "llvm/MC/MCAsmInfoELF.h"
+#include "llvm/MC/MCExpr.h"
 
 namespace llvm {
 class Triple;
@@ -34,6 +35,20 @@ class SuperHMCAsmInfo : public MCAsmInfoELF {
                              const MCTargetOptions &Options);
 };
 
-} // end namespace llvm
+namespace SH {
+using Specifier = uint16_t;
+enum {
+  S_None,
+
+  S_SH_NONE = MCSymbolRefExpr::FirstTargetSpecifier,
+  S_GOT,
+  S_GOT_OFF,
+  S_GOT_PCREL,
+  S_PCREL,
+  S_DIR,
+};
+} // namespace SH
+
+} // namespace llvm
 
 #endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 3f5d826bd1b13..55383441344a5 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -11,11 +11,14 @@
 //===----------------------------------------------------------------------===//
 
 
+#include "SuperHFixupKinds.h"
+#include "SuperHMCAsmInfo.h"
 #include "SuperHMCTargetDesc.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/BinaryFormat/ELF.h"
+#include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
@@ -67,9 +70,17 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
 
+  unsigned getBranchTargetOpValue(const MCInst &MI, const MCExpr *Expr,
+                          SmallVectorImpl<MCFixup> &Fixups,
+                          const MCSubtargetInfo &STI) const;
+
   unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
+
+  unsigned getOpBits(const MCInst &MI,
+                     SmallVectorImpl<MCFixup> &Fixups,
+                     const MCSubtargetInfo &STI) const;
 };
 
 } // end namespace
@@ -94,12 +105,25 @@ static bool isOpcode32(uint32_t Opcode) {
   return Opcode > 0xFFFF; 
 }
 
+// Helper that gets the bits for the given instruction.
+unsigned SuperHMCCodeEmitter::getOpBits(const MCInst &MI,
+                                        SmallVectorImpl<MCFixup> &Fixups,
+                                        const MCSubtargetInfo &STI) const {
+  MCInst Inst = MCInst();
+  Inst.setOpcode(MI.getOpcode());
+  for(unsigned i = 0; i < MI.getNumOperands(); i++) {
+    Inst.addOperand(MCOperand::createImm(0));
+  }
+
+  return getBinaryCodeForInstr(Inst, Fixups, STI);
+}
+
 void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
                                            SmallVectorImpl<char> &CB,
                                            SmallVectorImpl<MCFixup> &Fixups,
                                            const MCSubtargetInfo &STI) const {
 
-  uint32_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
+  uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
 
   // NOTE:  All base instructions are 16-bit in SH ASM
   //        But some instructions may be 32-bit for eg. SH2A or the DSP extensions.
@@ -117,9 +141,19 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
   ++MCNumEmitted;
 }
 
+unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, 
+                                                     const MCExpr *Expr,
+                                                     SmallVectorImpl<MCFixup> &Fixups,
+                                                     const MCSubtargetInfo &STI) const {
+  return getExprOpValue(MI, Expr, Fixups, STI);
+}
+
 unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
                                              SmallVectorImpl<MCFixup> &Fixups,
                                              const MCSubtargetInfo &STI) const {
+  if (!Expr)
+    return 0;
+
   MCExpr::ExprKind Kind = Expr->getKind();
 
   // Binary Op
@@ -128,12 +162,11 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
     Kind = Expr->getKind();
   }
 
-  // Symbol Reference
   if (Kind == MCExpr::SymbolRef) {
 
     // NOTE:  A few (DSP and SH2A) instructions are 32-bits wide.
     //        We handle those quite crudely.
-    uint32_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
+    uint32_t OpCode = getOpBits(MI, Fixups, STI);
     Fixups.push_back(MCFixup::create(0, Expr, isOpcode32(OpCode) ? FK_Data_4 : FK_Data_2, true));
     return 0;
   }
@@ -146,7 +179,8 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
   return 0;
 }
 
-unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI, 
+                             const MCOperand &MO,
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const {
   if (MO.isReg())
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
index cd8db84311001..86e98b93b96a5 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
@@ -28,10 +28,9 @@ SuperHTargetELFStreamer::SuperHTargetELFStreamer(MCStreamer &S,
     : SuperHTargetStreamer(S) {
   ELFObjectWriter &W = getStreamer().getWriter();
   unsigned EFlags = W.getELFHeaderEFlags();
-
   W.setELFHeaderEFlags(EFlags);
 }
 
 MCELFStreamer &SuperHTargetELFStreamer::getStreamer() {
   return static_cast<MCELFStreamer &>(Streamer);
-}
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index c0d62f8fb03f8..911234e3efefc 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -27,11 +27,13 @@ class SuperHTargetMachine;
 
 FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel);
 FunctionPass *createSuperHFillDelaySlotsPass();
+FunctionPass *createSuperHConstantIslandPass();
 
 void initializeSuperHDAGToDAGISelLegacyPass(PassRegistry &);
 void initializeSuperHAsmPrinterPass(PassRegistry &);
 void initializeSuperHAsmPrinterPass(PassRegistry &);
 void initializeSuperHFillDelaySlotsPass(PassRegistry &);
+void initializeSuperHConstantIslandsPass(PassRegistry &);
 } // namespace llvm
 
 
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index c62e23430d2b5..884266d52eff9 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -11,16 +11,20 @@
 //
 //===-----------------------------------------------------------------------===//
 
+#include "MCTargetDesc/SuperHBaseInfo.h"
 #include "MCTargetDesc/SuperHInstPrinter.h"
 #include "MCTargetDesc/SuperHMCAsmInfo.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "MCTargetDesc/SuperHTargetStreamer.h"
 #include "SuperH.h"
+#include "SuperHConstantPoolValue.h"
 #include "SuperHMCInstLower.h"
 #include "TargetInfo/SuperHTargetInfo.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Casting.h"
 
 using namespace llvm;
 
@@ -29,6 +33,19 @@ using namespace llvm;
 namespace {
 
 class SuperHAsmPrinter : public AsmPrinter {
+public:
+  static char ID;
+
+private:
+
+  /// MCP - Keep a pointer to constantpool entries of the current
+  /// MachineFunction.
+  const MachineConstantPool *MCP;
+
+  /// InConstantPool - Maintain state when emitting a sequence of constant
+  /// pool entries so we can properly mark them as data regions.
+  bool InConstantPool = false;
+
 	SuperHTargetStreamer &getTargetStreamer() {
 		return static_cast<SuperHTargetStreamer &>(
 			*OutStreamer->getTargetStreamer());
@@ -37,16 +54,22 @@ class SuperHAsmPrinter : public AsmPrinter {
 public:
   explicit SuperHAsmPrinter(TargetMachine &TM,
                            std::unique_ptr<MCStreamer> Streamer)
-      : AsmPrinter(TM, std::move(Streamer), ID) {}
+      : AsmPrinter(TM, std::move(Streamer), ID), MCP(nullptr) {}
 
   StringRef getPassName() const override { return "SuperH Assembly Printer"; }
+  bool runOnMachineFunction(MachineFunction &F) override;
 
   void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
   void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
 
   void emitFunctionBodyStart() override;
+  void emitFunctionBodyEnd() override;
   void emitInstruction(const MachineInstr *MI) override;
 
+  // We emit them ourselves.
+  void emitConstantPool() override { }
+  void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
+
   static const char *getRegisterName(MCRegister Reg) {
     return SuperHInstPrinter::getRegisterName(Reg);
   }
@@ -55,23 +78,63 @@ class SuperHAsmPrinter : public AsmPrinter {
                        const char *ExtraCode, raw_ostream &O) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &O) override;
-
-  static char ID;
 };
 
 } // namespace
 
+bool SuperHAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+  MCP = MF.getConstantPool();
+  return AsmPrinter::runOnMachineFunction(MF);
+}
 
-void SuperHAsmPrinter::emitFunctionBodyStart() {
-  AsmPrinter::emitFunctionBodyStart();
+
+
+
+//===----------------------------------------------------------------------===//
+//                                   Utilities
+//===----------------------------------------------------------------------===//
+
+// Convert a SuperH-specific constant pool modifier into the associated
+// specifier.
+static uint8_t getSpecifierFromModifier(SHCP::SHCPModifier Modifier) {
+  switch (Modifier) {
+  case SHCP::SHCPModifier::DIR:
+  case SHCP::SHCPModifier::no_modifier:
+    return SHII::MO_DIR;
+  default:
+    return SHII::MO_DIR;
+  }
 }
 
-void SuperHAsmPrinter::emitInstruction(const MachineInstr *MI) {
-  SuperHMCInstLower MCInstLowering(OutContext, *this);
 
-  MCInst I;
-  MCInstLowering.lowerInstruction(*MI, I);
-  EmitToStreamer(*OutStreamer, I);
+
+
+//===----------------------------------------------------------------------===//
+//                                  Operands
+//===----------------------------------------------------------------------===//
+
+void SuperHAsmPrinter::printOperand(const MachineInstr *MI, int OpNo, raw_ostream &O) {
+  const MachineOperand &MO = MI->getOperand(OpNo);
+
+  switch (MO.getType()) {
+  case MachineOperand::MO_Register:
+    O << StringRef(getRegisterName(MO.getReg())).lower();
+    break;
+  case MachineOperand::MO_Immediate:
+    O << MO.getImm();
+    break;
+  case MachineOperand::MO_GlobalAddress:
+    O << getSymbol(MO.getGlobal());
+    break;
+  case MachineOperand::MO_ExternalSymbol:
+    O << *GetExternalSymbolSymbol(MO.getSymbolName());
+    break;
+  case MachineOperand::MO_MachineBasicBlock:
+    O << *MO.getMBB()->getSymbol();
+    break;
+  default:
+    llvm_unreachable("Not implemented yet!");
+  }
 }
 
 bool SuperHAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -79,13 +142,124 @@ bool SuperHAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
   if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
     return false;
 
+  const MachineOperand &MO = MI->getOperand(OpNo);
+  if (MO.getType() == MachineOperand::MO_GlobalAddress)
+    PrintSymbolOperand(MO, O); // Print global symbols.
+  else
+    printOperand(MI, OpNo, O); // Fallback to ordinary cases.
 
-	return false;
+  return false;
 }
 
 bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                        const char *ExtraCode, raw_ostream &O) {
-	return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, O);
+  if (ExtraCode && ExtraCode[0])
+    return true; // Unknown modifier
+
+  const MachineOperand &MO = MI->getOperand(OpNo);
+
+  // Print direct memory operands.
+  if (MO.isGlobal() || MO.isSymbol() || MO.isMCSymbol()) {
+    PrintSymbolOperand(MO, O);
+    return false;
+  }
+  return false;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                                Constant Pool
+//===----------------------------------------------------------------------===//
+
+
+void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
+  const DataLayout &DL = getDataLayout();
+  int Size = DL.getTypeAllocSize(MCPV->getType());
+
+  MCSymbol *MCSym;
+  SuperHConstantPoolValue *SCPV = static_cast<SuperHConstantPoolValue*>(MCPV);
+  if (SCPV->isBlockAddress()) {
+    const BlockAddress *BA =
+      cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
+    MCSym = GetBlockAddressSymbol(BA);
+  } else if (SCPV->isGlobalValue()) {
+    const GlobalValue *GV = cast<SuperHConstantPoolConstant>(SCPV)->getGV();
+    MCSym = getSymbolPreferLocal(*GV);
+  } else {
+    assert(SCPV->isExtSymbol() && "unrecognized constant pool value");
+    auto Sym = cast<SuperHConstantPoolSymbol>(SCPV)->getSymbol();
+    MCSym = GetExternalSymbolSymbol(Sym);
+  }
+
+  // Create an MCSymbol for the reference.
+  const MCExpr *Expr = MCSymbolRefExpr::create(
+    MCSym, 
+    OutContext
+  );
+  OutStreamer->emitValue(Expr, Size);
+}
+
+void SuperHAsmPrinter::emitFunctionBodyStart() {
+  AsmPrinter::emitFunctionBodyStart();
+}
+
+void SuperHAsmPrinter::emitFunctionBodyEnd() {
+
+  // Make sure to terminate any constant pools that were at the end
+  // of the function.
+  if (!InConstantPool)
+    return;
+
+  InConstantPool = false;
+  OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
+}
+
+
+void SuperHAsmPrinter::emitInstruction(const MachineInstr *MI) {
+  const SuperHSubtarget &STI = MF->getSubtarget<SuperHSubtarget>();
+  const DataLayout &DL = getDataLayout();
+  MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
+  SuperHTargetStreamer &STS = static_cast<SuperHTargetStreamer &>(TS);
+
+  // If we just ended a constant pool, mark it as such.
+  if (InConstantPool && MI->getOpcode() != SH::CONSTPOOL_ENTRY) {
+    OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
+    InConstantPool = false;
+  }
+
+  unsigned Opc = MI->getOpcode();
+  switch (Opc) {
+  default: {
+    SuperHMCInstLower MCInstLowering(OutContext, *this);
+
+    MCInst I;
+    MCInstLowering.lowerInstruction(*MI, I);
+    EmitToStreamer(*OutStreamer, I);
+    return;
+  }
+
+  case SH::CONSTPOOL_ENTRY: {
+    unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
+    unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
+
+    // If this is the first entry of the pool, mark it.
+    if (!InConstantPool) {
+      OutStreamer->emitDataRegion(MCDR_DataRegion);
+      InConstantPool = true;
+    }
+
+    OutStreamer->emitLabel(GetCPISymbol(LabelId));
+
+    const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
+    if (MCPE.isMachineConstantPoolEntry())
+      emitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
+    else
+      emitGlobalConstant(DL, MCPE.Val.ConstVal);
+    return;
+  }
+  }
 }
 
 char SuperHAsmPrinter::ID = 0;
diff --git a/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
new file mode 100644
index 0000000000000..3a139ba14acf0
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
@@ -0,0 +1,110 @@
+//===-- SuperHBasicBlockInfo.cpp - Basic Block Information ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHBasicBlockInfo.h"
+
+#define DEBUG_TYPE "sh-bb-utils"
+
+using namespace llvm;
+
+namespace llvm {
+
+void SuperHBasicBlockUtils::computeBlockSize(MachineBasicBlock *MBB) {
+  LLVM_DEBUG(dbgs() << "computeBlockSize: " << MBB->getName() << "\n");
+  BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];
+  BBI.Size = 0;
+  BBI.Unalign = 0;
+  BBI.PostAlign = Align(1);
+
+  for (MachineInstr &I : *MBB) {
+    BBI.Size += TII->getInstSizeInBytes(I);
+    // For inline asm, getInstSizeInBytes returns a conservative estimate.
+    // The actual size may be smaller, but still a multiple of the instr size.
+    if (I.isInlineAsm())
+      BBI.Unalign = 2;
+  }
+}
+
+/// getOffsetOf - Return the current offset of the specified machine instruction
+/// from the start of the function.  This offset changes as stuff is moved
+/// around inside the function.
+unsigned SuperHBasicBlockUtils::getOffsetOf(MachineInstr *MI) const {
+  const MachineBasicBlock *MBB = MI->getParent();
+
+  // The offset is composed of two things: the sum of the sizes of all MBB's
+  // before this instruction's block, and the offset from the start of the block
+  // it is in.
+  unsigned Offset = BBInfo[MBB->getNumber()].Offset;
+
+  // Sum instructions before MI in MBB.
+  for (MachineBasicBlock::const_iterator I = MBB->begin(); &*I != MI; ++I) {
+    assert(I != MBB->end() && "Didn't find MI in its own basic block?");
+    Offset += TII->getInstSizeInBytes(*I);
+  }
+  return Offset;
+}
+
+/// isBBInRange - Returns true if the distance between specific MI and
+/// specific BB can fit in MI's displacement field.
+bool SuperHBasicBlockUtils::isBBInRange(MachineInstr *MI,
+                                     MachineBasicBlock *DestBB,
+                                     unsigned MaxDisp) const {
+  unsigned PCAdj      = 4;
+  unsigned BrOffset   = getOffsetOf(MI) + PCAdj;
+  unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
+
+  LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB)
+                    << " from " << printMBBReference(*MI->getParent())
+                    << " max delta=" << MaxDisp << " from " << getOffsetOf(MI)
+                    << " to " << DestOffset << " offset "
+                    << int(DestOffset - BrOffset) << "\t" << *MI);
+
+  if (BrOffset <= DestOffset) {
+    // Branch before the Dest.
+    if (DestOffset-BrOffset <= MaxDisp)
+      return true;
+  } else {
+    if (BrOffset-DestOffset <= MaxDisp)
+      return true;
+  }
+  return false;
+}
+
+void SuperHBasicBlockUtils::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
+  assert(BB->getParent() == &MF &&
+         "Basic block is not a child of the current function.\n");
+
+  unsigned BBNum = BB->getNumber();
+  LLVM_DEBUG(dbgs() << "Adjust block:\n"
+             << " - name: " << BB->getName() << "\n"
+             << " - number: " << BB->getNumber() << "\n"
+             << " - function: " << MF.getName() << "\n"
+             << "   - blocks: " << MF.getNumBlockIDs() << "\n");
+
+  for(unsigned i = BBNum + 1, e = MF.getNumBlockIDs(); i < e; ++i) {
+    // Get the offset and known bits at the end of the layout predecessor.
+    // Include the alignment of the current block.
+    const Align Align = MF.getBlockNumbered(i)->getAlignment();
+    const unsigned Offset = BBInfo[i - 1].postOffset(Align);
+    const unsigned KnownBits = BBInfo[i - 1].postKnownBits(Align);
+
+    // This is where block i begins.  Stop if the offset is already correct,
+    // and we have updated 2 blocks.  This is the maximum number of blocks
+    // changed before calling this function.
+    if (i > BBNum + 2 &&
+        BBInfo[i].Offset == Offset &&
+        BBInfo[i].KnownBits == KnownBits)
+      break;
+
+    BBInfo[i].Offset = Offset;
+    BBInfo[i].KnownBits = KnownBits;
+  }
+}
+
+
+} // namespace llvm
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
new file mode 100644
index 0000000000000..f0039cbc5eb7f
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
@@ -0,0 +1,157 @@
+//===-- SuperHBasicBlockInfo.h - Basic Block Information --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility functions and data structure for computing block size.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHBASICBLOCKINFO_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHBASICBLOCKINFO_H
+
+#include "SuperHInstrInfo.h"
+#include "SuperHMachineFunctionInfo.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cstdint>
+
+namespace llvm {
+
+struct BasicBlockInfo;
+using BBInfoVector = SmallVectorImpl<BasicBlockInfo>;
+
+/// UnknownPadding - Return the worst case padding that could result from
+/// unknown offset bits.  This does not include alignment padding caused by
+/// known offset bits.
+///
+/// @param Alignment alignment
+/// @param KnownBits Number of known low offset bits.
+inline unsigned UnknownPadding(Align Alignment, unsigned KnownBits) {
+  if (KnownBits < Log2(Alignment))
+    return Alignment.value() - (1ull << KnownBits);
+  return 0;
+}
+
+/// BasicBlockInfo - Information about the offset and size of a single
+/// basic block.
+struct BasicBlockInfo {
+  /// Offset - Distance from the beginning of the function to the beginning
+  /// of this basic block.
+  ///
+  /// Offsets are computed assuming worst case padding before an aligned
+  /// block. This means that subtracting basic block offsets always gives a
+  /// conservative estimate of the real distance which may be smaller.
+  ///
+  /// Because worst case padding is used, the computed offset of an aligned
+  /// block may not actually be aligned.
+  unsigned Offset = 0;
+
+  /// Size - Size of the basic block in bytes.  If the block contains
+  /// inline assembly, this is a worst case estimate.
+  ///
+  /// The size does not include any alignment padding whether from the
+  /// beginning of the block, or from an aligned jump table at the end.
+  unsigned Size = 0;
+
+  /// KnownBits - The number of low bits in Offset that are known to be
+  /// exact.  The remaining bits of Offset are an upper bound.
+  uint8_t KnownBits = 0;
+
+  /// Unalign - When non-zero, the block contains instructions (inline asm)
+  /// of unknown size.  The real size may be smaller than Size bytes by a
+  /// multiple of 1 << Unalign.
+  uint8_t Unalign = 0;
+
+  /// PostAlign - When > 1, the block terminator contains a .align
+  /// directive, so the end of the block is aligned to PostAlign bytes.
+  Align PostAlign;
+
+  BasicBlockInfo() = default;
+
+  /// Compute the number of known offset bits internally to this block.
+  /// This number should be used to predict worst case padding when
+  /// splitting the block.
+  unsigned internalKnownBits() const {
+    unsigned Bits = Unalign ? Unalign : KnownBits;
+    // If the block size isn't a multiple of the known bits, assume the
+    // worst case padding.
+    if (Size & ((1u << Bits) - 1))
+      Bits = llvm::countr_zero(Size);
+    return Bits;
+  }
+
+  /// Compute the offset immediately following this block.  If Align is
+  /// specified, return the offset the successor block will get if it has
+  /// this alignment.
+  unsigned postOffset(Align Alignment = Align(1)) const {
+    unsigned PO = Offset + Size;
+    const Align PA = std::max(PostAlign, Alignment);
+    if (PA == Align(1))
+      return PO;
+    // Add alignment padding from the terminator.
+    return PO + UnknownPadding(PA, internalKnownBits());
+  }
+
+  /// Compute the number of known low bits of postOffset.  If this block
+  /// contains inline asm, the number of known bits drops to the
+  /// instruction alignment.  An aligned terminator may increase the number
+  /// of know bits.
+  /// If LogAlign is given, also consider the alignment of the next block.
+  unsigned postKnownBits(Align Align = llvm::Align(1)) const {
+    return std::max(Log2(std::max(PostAlign, Align)), internalKnownBits());
+  }
+};
+
+class SuperHBasicBlockUtils {
+
+private:
+  MachineFunction &MF;
+  const SuperHInstrInfo *TII = nullptr;
+  SmallVector<BasicBlockInfo, 8> BBInfo;
+
+public:
+  SuperHBasicBlockUtils(MachineFunction &MF) : MF(MF) {
+    TII =
+      static_cast<const SuperHInstrInfo*>(MF.getSubtarget().getInstrInfo());
+  }
+
+  void computeAllBlockSizes() {
+    BBInfo.resize(MF.getNumBlockIDs());
+    for (MachineBasicBlock &MBB : MF)
+      computeBlockSize(&MBB);
+  }
+
+  void computeBlockSize(MachineBasicBlock *MBB);
+
+  unsigned getOffsetOf(MachineInstr *MI) const;
+
+  unsigned getOffsetOf(MachineBasicBlock *MBB) const {
+    return BBInfo[MBB->getNumber()].Offset;
+  }
+
+  void adjustBBOffsetsAfter(MachineBasicBlock *MBB);
+
+  void adjustBBSize(MachineBasicBlock *MBB, int Size) {
+    BBInfo[MBB->getNumber()].Size += Size;
+  }
+
+  bool isBBInRange(MachineInstr *MI, MachineBasicBlock *DestBB,
+                   unsigned MaxDisp) const;
+
+  void insert(unsigned BBNum, BasicBlockInfo BBI) {
+    BBInfo.insert(BBInfo.begin() + BBNum, BBI);
+  }
+
+  void clear() { BBInfo.clear(); }
+
+  BBInfoVector &getBBInfo() { return BBInfo; }
+
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_SUPERH_SUPERHBASICBLOCKINFO_H
diff --git a/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
new file mode 100644
index 0000000000000..226136c6fd73f
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
@@ -0,0 +1,1184 @@
+//===- SuperHConstantIslandPass.cpp - SuperH constant islands -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that splits the constant pool up into 'islands'
+// which are scattered through-out the function.  This is required due to the
+// limited pc-relative displacements that SuperH has.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SuperHInstPrinter.h"
+#include "SuperHBasicBlockInfo.h"
+#include "SuperHMachineFunctionInfo.h"
+#include "SuperHSubtarget.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
+#include <memory>
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-cp-islands"
+
+#define SH_CP_ISLANDS_OPT_NAME \
+  "SH constant island placement and branch shortening pass"
+
+static cl::opt<unsigned>
+CPMaxIteration("sh-constant-island-max-iteration", cl::Hidden, cl::init(30),
+          cl::desc("The max number of iteration for converge"));
+
+namespace {
+
+  /// SuperHConstantIslands - Due to limited PC-relative displacements, SH
+  /// requires constant pool entries to be scattered among the instructions
+  /// inside a function.  To do this, it completely ignores the normal LLVM
+  /// constant pool; instead, it places constants wherever it feels like with
+  /// special instructions.
+  ///
+  /// The terminology used in this pass includes:
+  ///   Islands - Clumps of constants placed in the function.
+  ///   Water   - Potential places where an island could be formed.
+  ///   CPE     - A constant pool entry that has been placed somewhere, which
+  ///             tracks a list of users.
+  class SuperHConstantIslands : public MachineFunctionPass {
+  public:
+    static char ID;
+
+  private:
+    std::unique_ptr<SuperHBasicBlockUtils> BBUtils = nullptr;
+
+    /// WaterList - A sorted list of basic blocks where islands could be placed
+    /// (i.e. blocks that don't fall through to the following block, due
+    /// to a return, unreachable, or unconditional branch).
+    std::vector<MachineBasicBlock*> WaterList;
+
+    /// NewWaterList - The subset of WaterList that was created since the
+    /// previous iteration by inserting unconditional branches.
+    SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
+
+    using water_iterator = std::vector<MachineBasicBlock *>::iterator;
+
+    /// CPUser - One user of a constant pool, keeping the machine instruction
+    /// pointer, the constant pool being referenced, and the max displacement
+    /// allowed from the instruction to the CP.  The HighWaterMark records the
+    /// highest basic block where a new CPEntry can be placed.  To ensure this
+    /// pass terminates, the CP entries are initially placed at the end of the
+    /// function and then move monotonically to lower addresses.  The
+    /// exception to this rule is when the current CP entry for a particular
+    /// CPUser is out of range, but there is another CP entry for the same
+    /// constant value in range.  We want to use the existing in-range CP
+    /// entry, but if it later moves out of range, the search for new water
+    /// should resume where it left off.  The HighWaterMark is used to record
+    /// that point.
+    struct CPUser {
+      MachineInstr *MI;
+      MachineInstr *CPEMI;
+      MachineBasicBlock *HighWaterMark;
+      unsigned MaxDisp;
+      bool NegOk;
+      bool IsSoImm;
+      bool KnownAlignment = false;
+
+      CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,
+             bool neg, bool soimm)
+        : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(neg), IsSoImm(soimm) {
+        HighWaterMark = CPEMI->getParent();
+      }
+
+      /// getMaxDisp - Returns the maximum displacement supported by MI.
+      /// Correct for unknown alignment.
+      /// Conservatively subtract 2 bytes to handle weird alignment effects.
+      unsigned getMaxDisp() const {
+        return (KnownAlignment ? MaxDisp : MaxDisp - 2) - 2;
+      }
+    };
+
+    /// CPUsers - Keep track of all of the machine instructions that use various
+    /// constant pools and their max displacement.
+    std::vector<CPUser> CPUsers;
+
+    /// CPEntry - One per constant pool entry, keeping the machine instruction
+    /// pointer, the constpool index, and the number of CPUser's which
+    /// reference this entry.
+    struct CPEntry {
+      MachineInstr *CPEMI;
+      unsigned CPI;
+      unsigned RefCount;
+
+      CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0)
+        : CPEMI(cpemi), CPI(cpi), RefCount(rc) {}
+    };
+
+    /// CPEntries - Keep track of all of the constant pool entry machine
+    /// instructions. For each original constpool index (i.e. those that existed
+    /// upon entry to this pass), it keeps a vector of entries.  Original
+    /// elements are cloned as we go along; the clones are put in the vector of
+    /// the original element, but have distinct CPIs.
+    ///
+    /// The first half of CPEntries contains generic constants, the second half
+    /// contains jump tables. Use getCombinedIndex on a generic CPEMI to look up
+    /// which vector it will be in here.
+    std::vector<std::vector<CPEntry>> CPEntries;
+
+    /// ImmBranch - One per immediate branch, keeping the machine instruction
+    /// pointer, conditional or unconditional, the max displacement,
+    /// and (if isCond is true) the corresponding unconditional branch
+    /// opcode.
+    struct ImmBranch {
+      MachineInstr *MI;
+      unsigned MaxDisp : 12;
+
+      ImmBranch(MachineInstr *mi, unsigned maxdisp)
+        : MI(mi), MaxDisp(maxdisp) {}
+    };
+
+    /// ImmBranches - Keep track of all the immediate branch instructions.
+    std::vector<ImmBranch> ImmBranches;
+
+    MachineFunction *MF;
+    MachineConstantPool *MCP;
+    const SuperHInstrInfo *TII;
+    const SuperHSubtarget *STI;
+    SuperHMachineFunctionInfo *SFI;
+    MachineDominatorTree *DT = nullptr;
+    bool isPIC;
+
+  public:
+
+    SuperHConstantIslands() : MachineFunctionPass(ID) {}
+
+    bool runOnMachineFunction(MachineFunction &MF) override;
+
+    void getAnalysisUsage(AnalysisUsage &AU) const override {
+      AU.addRequired<MachineDominatorTreeWrapperPass>();
+      MachineFunctionPass::getAnalysisUsage(AU);
+    }
+
+    MachineFunctionProperties getRequiredProperties() const override {
+      return MachineFunctionProperties().setNoVRegs();
+    }
+
+    StringRef getPassName() const override {
+      return SH_CP_ISLANDS_OPT_NAME;
+    }
+
+  private:
+    bool BBHasFallthrough(MachineBasicBlock *MBB);
+    void doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs);
+    CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
+    Align getCPEAlign(const MachineInstr *CPEMI);
+    void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs);
+    MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI);
+    void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
+    bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI);
+    unsigned getCombinedIndex(const MachineInstr *CPEMI);
+    int findInRangeCPEntry(CPUser& U, unsigned UserOffset);
+    bool findAvailableWater(CPUser&U, unsigned UserOffset,
+                            water_iterator &WaterIter, bool CloserWater);
+    void createNewWater(unsigned CPUserIndex, unsigned UserOffset,
+                        MachineBasicBlock *&NewMBB);
+    bool handleConstantPoolUser(unsigned CPUserIndex, bool CloserWater);
+    void removeDeadCPEMI(MachineInstr *CPEMI);
+    bool removeUnusedCPEntries();
+    bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
+                          MachineInstr *CPEMI, unsigned Disp, bool NegOk,
+                          bool DoDump = false);
+    bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water,
+                        CPUser &U, unsigned &Growth);
+    bool fixupImmediateBr(ImmBranch &Br);
+
+    unsigned getUserOffset(CPUser&) const;
+    void verify();
+
+    bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
+                         unsigned Disp, bool NegativeOK, bool IsSoImm = false);
+    bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
+                         const CPUser &U) {
+      return isOffsetInRange(UserOffset, TrialOffset,
+                             U.getMaxDisp(), U.NegOk, U.IsSoImm);
+    }
+
+  };
+
+} // end anonymous namespace
+
+char SuperHConstantIslands::ID = 0;
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                                  HELPERS
+//===----------------------------------------------------------------------===//
+
+// Align blocks where the previous block does not fall through. This may add
+// extra NOP's but they will not be executed. It uses the PrefLoopAlignment as a
+// measure of how much to align, and only runs at CodeGenOptLevel::Aggressive.
+static bool AlignBlocks(MachineFunction *MF, const SuperHSubtarget *STI) {
+  if (MF->getTarget().getOptLevel() != CodeGenOptLevel::Aggressive ||
+      MF->getFunction().hasOptSize())
+    return false;
+
+  auto *TLI = STI->getTargetLowering();
+  const Align Alignment = TLI->getPrefLoopAlignment();
+  if (Alignment < 4)
+    return false;
+
+  bool Changed = false;
+  bool PrevCanFallthrough = true;
+  for (auto &MBB : *MF) {
+    if (!PrevCanFallthrough) {
+      Changed = true;
+      MBB.setAlignment(Alignment);
+    }
+  }
+
+  return Changed;
+}
+
+/// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB
+/// ID.
+static bool CompareMBBNumbers(const MachineBasicBlock *LHS,
+                              const MachineBasicBlock *RHS) {
+  return LHS->getNumber() < RHS->getNumber();
+}
+
+/// getDispRange - Returns the maximum displacement that can fit in
+/// the specific unconditional branch instruction.
+static inline unsigned getDispRange(int Opc) {
+  return ((1<<8)-1)*4;
+}
+
+/// isOffsetInRange - Checks whether UserOffset (the location of a constant pool
+/// reference) is within MaxDisp of TrialOffset (a proposed location of a
+/// constant pool entry).
+/// UserOffset is computed by getUserOffset above to include PC adjustments. If
+/// the mod 4 alignment of UserOffset is not known, the uncertainty must be
+/// subtracted from MaxDisp instead. CPUser::getMaxDisp() does that.
+bool SuperHConstantIslands::isOffsetInRange(unsigned UserOffset,
+                                         unsigned TrialOffset, unsigned MaxDisp,
+                                         bool NegativeOK, bool IsSoImm) {
+  if (UserOffset <= TrialOffset) {
+    // User before the Trial.
+    if (TrialOffset - UserOffset <= MaxDisp)
+      return true;
+    // FIXME: Make use full range of soimm values.
+  } else if (NegativeOK) {
+    if (UserOffset - TrialOffset <= MaxDisp)
+      return true;
+    // FIXME: Make use full range of soimm values.
+  }
+  return false;
+}
+
+/// BBHasFallthrough - Return true if the specified basic block can fallthrough
+/// into the block immediately after it.
+bool SuperHConstantIslands::BBHasFallthrough(MachineBasicBlock *MBB) {
+  // Get the next machine basic block in the function.
+  MachineFunction::iterator MBBI = MBB->getIterator();
+  // Can't fall off end of function.
+  if (std::next(MBBI) == MBB->getParent()->end())
+    return false;
+
+  MachineBasicBlock *NextBB = &*std::next(MBBI);
+  if (!MBB->isSuccessor(NextBB))
+    return false;
+
+  // Try to analyze the end of the block. A potential fallthrough may already
+  // have an unconditional branch for whatever reason.
+  MachineBasicBlock *TBB, *FBB;
+  SmallVector<MachineOperand, 4> Cond;
+  bool TooDifficult = TII->analyzeBranch(*MBB, TBB, FBB, Cond);
+  return TooDifficult || FBB == nullptr;
+}
+
+/// getCPEAlign - Returns the required alignment of the constant pool entry
+/// represented by CPEMI.
+Align SuperHConstantIslands::getCPEAlign(const MachineInstr *CPEMI) {
+  unsigned CPI = getCombinedIndex(CPEMI);
+  assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");
+  return MCP->getConstants()[CPI].getAlign();
+}
+
+/// isWaterInRange - Returns true if a CPE placed after the specified
+/// Water (a basic block) will be in range for the specific MI.
+///
+/// Compute how much the function will grow by inserting a CPE after Water.
+bool SuperHConstantIslands::isWaterInRange(unsigned UserOffset,
+                                        MachineBasicBlock* Water, CPUser &U,
+                                        unsigned &Growth) {
+  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  const Align CPEAlign = getCPEAlign(U.CPEMI);
+  const unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPEAlign);
+  unsigned NextBlockOffset;
+  Align NextBlockAlignment;
+  MachineFunction::const_iterator NextBlock = Water->getIterator();
+  if (++NextBlock == MF->end()) {
+    NextBlockOffset = BBInfo[Water->getNumber()].postOffset();
+  } else {
+    NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset;
+    NextBlockAlignment = NextBlock->getAlignment();
+  }
+  unsigned Size = U.CPEMI->getOperand(2).getImm();
+  unsigned CPEEnd = CPEOffset + Size;
+
+  // The CPE may be able to hide in the alignment padding before the next
+  // block. It may also cause more padding to be required if it is more aligned
+  // that the next block.
+  if (CPEEnd > NextBlockOffset) {
+    Growth = CPEEnd - NextBlockOffset;
+    // Compute the padding that would go at the end of the CPE to align the next
+    // block.
+    Growth += offsetToAlignment(CPEEnd, NextBlockAlignment);
+
+    // If the CPE is to be inserted before the instruction, that will raise
+    // the offset of the instruction. Also account for unknown alignment padding
+    // in blocks between CPE and the user.
+    if (CPEOffset < UserOffset)
+      UserOffset += Growth + UnknownPadding(MF->getAlignment(), Log2(CPEAlign));
+  } else
+    // CPE fits in existing padding.
+    Growth = 0;
+
+  return isOffsetInRange(UserOffset, CPEOffset, U);
+}
+
+/// isCPEntryInRange - Returns true if the distance between specific MI and
+/// specific ConstPool entry instruction can fit in MI's displacement field.
+bool SuperHConstantIslands::isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
+                                      MachineInstr *CPEMI, unsigned MaxDisp,
+                                      bool NegOk, bool DoDump) {
+  unsigned CPEOffset = BBUtils->getOffsetOf(CPEMI);
+
+  if (DoDump) {
+    LLVM_DEBUG({
+        BBInfoVector &BBInfo = BBUtils->getBBInfo();
+      unsigned Block = MI->getParent()->getNumber();
+      const BasicBlockInfo &BBI = BBInfo[Block];
+      dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm()
+             << " max delta=" << MaxDisp
+             << format(" insn address=%#x", UserOffset) << " in "
+             << printMBBReference(*MI->getParent()) << ": "
+             << format("%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI
+             << format("CPE address=%#x offset=%+d: ", CPEOffset,
+                       int(CPEOffset - UserOffset));
+    });
+  }
+
+  return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk);
+}
+
+/// getUserOffset - Compute the offset of U.MI as seen by the hardware
+/// displacement computation.  Update U.KnownAlignment to match its current
+/// basic block location.
+unsigned SuperHConstantIslands::getUserOffset(CPUser &U) const {
+  unsigned UserOffset = BBUtils->getOffsetOf(U.MI);
+
+  SmallVectorImpl<BasicBlockInfo> &BBInfo = BBUtils->getBBInfo();
+  const BasicBlockInfo &BBI = BBInfo[U.MI->getParent()->getNumber()];
+  unsigned KnownBits = BBI.internalKnownBits();
+
+  // The value read from PC is offset from the actual instruction address.
+  UserOffset += 4;
+
+  // Because of inline assembly, we may not know the alignment (mod 4) of U.MI.
+  // Make sure U.getMaxDisp() returns a constrained range.
+  U.KnownAlignment = (KnownBits >= 2);
+  return UserOffset;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                          BASE IMPLEMENTATION
+//===----------------------------------------------------------------------===//
+
+bool SuperHConstantIslands::runOnMachineFunction(MachineFunction &mf) {
+  MF = &mf;
+  MCP = MF->getConstantPool();
+  BBUtils = std::make_unique<SuperHBasicBlockUtils>(mf);
+
+  LLVM_DEBUG(dbgs() << "***** SuperHConstantIslands: "
+                    << MCP->getConstants().size() << " CP entries, aligned to "
+                    << MCP->getConstantPoolAlign().value() << " bytes *****\n");
+
+  STI = &MF->getSubtarget<SuperHSubtarget>();
+  TII = STI->getInstrInfo();
+  isPIC = STI->getTargetLowering()->isPositionIndependent();
+  SFI = MF->getInfo<SuperHMachineFunctionInfo>();
+  DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
+
+  // Renumber all of the machine basic blocks in the function, guaranteeing that
+  // the numbers agree with the position of the block in the function.
+  MF->RenumberBlocks();
+
+  bool MadeChange = false;
+
+  // Align any non-fallthrough blocks
+  MadeChange |= AlignBlocks(MF, STI);
+
+  // Perform the initial placement of the constant pool entries.  To start with,
+  // we put them all at the end of the function.
+  std::vector<MachineInstr*> CPEMIs;
+  if (!MCP->isEmpty())
+    doInitialConstPlacement(CPEMIs);
+
+
+  // Iteratively place constant pool entries and fix up branches until there
+  // is no change.
+  unsigned NoCPIters = 0, NoBRIters = 0;
+  while (true) {
+    LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << " with " <<
+                         CPUsers.size() << " entries..." << '\n');
+    bool CPChange = false;
+    for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
+      // For most inputs, it converges in no more than 5 iterations.
+      // If it doesn't end in 10, the input may have huge BB or many CPEs.
+      // In this case, we will try different heuristics.
+      CPChange |= handleConstantPoolUser(i, NoCPIters >= CPMaxIteration / 2);
+    if (CPChange && ++NoCPIters > CPMaxIteration)
+      report_fatal_error("Constant Island pass failed to converge!");
+
+    // Clear NewWaterList now.  If we split a block for branches, it should
+    // appear as "new water" for the next iteration of constant pool placement.
+    NewWaterList.clear();
+
+    LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << " with " <<
+                         ImmBranches.size() << " entries..." << '\n');
+    bool BRChange = false;
+    for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) {
+      // Note: fixupImmediateBr can append to ImmBranches.
+      BRChange |= fixupImmediateBr(ImmBranches[i]);
+    }
+    if (BRChange && ++NoBRIters > 30)
+      report_fatal_error("Branch Fix Up pass failed to converge!");
+
+    if (!CPChange && !BRChange)
+      break;
+    MadeChange = true;
+  }
+
+  BBUtils->clear();
+  CPUsers.clear();
+  CPEntries.clear();
+  WaterList.clear();
+  ImmBranches.clear();
+  return MadeChange;
+}
+
+/// initializeFunctionInfo - Do the initial scan of the function, building up
+/// information about the sizes of each block, the location of all the water,
+/// and finding all of the constant pool users.
+void SuperHConstantIslands::
+initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
+
+  BBUtils->computeAllBlockSizes();
+  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+
+  // The known bits of the entry block offset are determined by the function
+  // alignment.
+  BBInfo.front().KnownBits = Log2(MF->getAlignment());
+
+  // Compute block offsets and known bits.
+  BBUtils->adjustBBOffsetsAfter(&MF->front());
+
+  // Now go back through the instructions and build up our data structures.
+  for (MachineBasicBlock &MBB : *MF) {
+
+    // If this block doesn't fall through into the next MBB, then this is
+    // 'water' that a constant pool island could be placed.
+    if (!BBHasFallthrough(&MBB))
+      WaterList.push_back(&MBB);
+
+    for (MachineInstr &I : MBB) {
+      if (I.isDebugInstr())
+        continue;
+
+      unsigned Opc = I.getOpcode();
+      if (I.isBranch()) {
+        unsigned Bits = 8;
+        unsigned Scale = 4;
+        switch (Opc) {
+        default:
+          continue;
+
+        case SH::BF:
+        case SH::BFS:
+        case SH::BT:
+        case SH::BTS:
+          Bits = 8;
+          Scale = 4;
+          break;
+        case SH::BRA:
+        case SH::BSR:
+          Bits = 12;
+          Scale = 4;
+          break;
+        }
+
+
+        // Record this immediate branch.
+        unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
+        ImmBranches.push_back(ImmBranch(&I, MaxOffs));
+      }
+
+      if (Opc == SH::CONSTPOOL_ENTRY)
+        continue;
+
+      // Scan the instructions for constant pool operands.
+      for (unsigned op = 0, e = I.getNumOperands(); op != e; ++op) {
+        if (I.getOperand(op).isCPI()) {
+          bool NegOk = false;
+          bool IsSoImm = false;
+
+          unsigned CPI = I.getOperand(op).getIndex();
+          MachineInstr *CPEMI = CPEMIs[CPI];
+          unsigned MaxOffs = ((1 << 8)-1) * 4;
+          CPUsers.push_back(CPUser(&I, CPEMI, MaxOffs, NegOk, IsSoImm));
+
+          // Increment corresponding CPEntry reference count.
+          CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
+          assert(CPE && "Cannot find a corresponding CPEntry!");
+          CPE->RefCount++;
+
+          // Instructions can only use one CP entry, don't bother scanning the
+          // rest of the operands.
+          break;
+
+        }
+      }
+    }
+  }
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                            CONSTPOOL MANAGMENT
+//===----------------------------------------------------------------------===//
+
+/// removeDeadCPEMI - Remove a dead constant pool entry instruction. Update
+/// sizes and offsets of impacted basic blocks.
+void SuperHConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
+  MachineBasicBlock *CPEBB = CPEMI->getParent();
+  unsigned Size = CPEMI->getOperand(2).getImm();
+  CPEMI->eraseFromParent();
+  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  BBUtils->adjustBBSize(CPEBB, -Size);
+  // All succeeding offsets have the current size value added in, fix this.
+  if (CPEBB->empty()) {
+    BBInfo[CPEBB->getNumber()].Size = 0;
+
+    // This block no longer needs to be aligned.
+    CPEBB->setAlignment(Align(1));
+  } else {
+    // Entries are sorted by descending alignment, so realign from the front.
+    CPEBB->setAlignment(getCPEAlign(&*CPEBB->begin()));
+  }
+
+  BBUtils->adjustBBOffsetsAfter(CPEBB);
+}
+
+/// removeUnusedCPEntries - Remove constant pool entries whose refcounts
+/// are zero.
+bool SuperHConstantIslands::removeUnusedCPEntries() {
+  unsigned MadeChange = false;
+  for (std::vector<CPEntry> &CPEs : CPEntries) {
+    for (CPEntry &CPE : CPEs) {
+      if (CPE.RefCount == 0 && CPE.CPEMI) {
+        removeDeadCPEMI(CPE.CPEMI);
+        CPE.CPEMI = nullptr;
+        MadeChange = true;
+      }
+    }
+  }
+  return MadeChange;
+}
+
+/// decrementCPEReferenceCount - find the constant pool entry with index CPI
+/// and instruction CPEMI, and decrement its refcount.  If the refcount
+/// becomes 0 remove the entry and instruction.  Returns true if we removed
+/// the entry, false if we didn't.
+bool SuperHConstantIslands::decrementCPEReferenceCount(unsigned CPI,
+                                                    MachineInstr *CPEMI) {
+  // Find the old entry. Eliminate it if it is no longer used.
+  CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
+  assert(CPE && "Unexpected!");
+  if (--CPE->RefCount == 0) {
+    removeDeadCPEMI(CPEMI);
+    CPE->CPEMI = nullptr;
+    return true;
+  }
+  return false;
+}
+
+unsigned SuperHConstantIslands::getCombinedIndex(const MachineInstr *CPEMI) {
+  if (CPEMI->getOperand(1).isCPI())
+    return CPEMI->getOperand(1).getIndex();
+
+  return 0;
+}
+/// LookForCPEntryInRange - see if the currently referenced CPE is in range;
+/// if not, see if an in-range clone of the CPE is in range, and if so,
+/// change the data structures so the user references the clone.  Returns:
+/// 0 = no existing entry found
+/// 1 = entry found, and there were no code insertions or deletions
+/// 2 = entry found, and there were code insertions or deletions
+int SuperHConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) {
+  MachineInstr *UserMI = U.MI;
+  MachineInstr *CPEMI  = U.CPEMI;
+
+  // Check to see if the CPE is already in-range.
+  if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,
+                       true)) {
+    LLVM_DEBUG(dbgs() << "In range\n");
+    return 1;
+  }
+
+  // No.  Look for previously created clones of the CPE that are in range.
+  unsigned CPI = getCombinedIndex(CPEMI);
+  std::vector<CPEntry> &CPEs = CPEntries[CPI];
+  for (CPEntry &CPE : CPEs) {
+    // We already tried this one
+    if (CPE.CPEMI == CPEMI)
+      continue;
+    // Removing CPEs can leave empty entries, skip
+    if (CPE.CPEMI == nullptr)
+      continue;
+    if (isCPEntryInRange(UserMI, UserOffset, CPE.CPEMI, U.getMaxDisp(),
+                         U.NegOk)) {
+      LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" << CPE.CPI
+                        << "\n");
+      // Point the CPUser node to the replacement
+      U.CPEMI = CPE.CPEMI;
+      // Change the CPI in the instruction operand to refer to the clone.
+      for (MachineOperand &MO : UserMI->operands())
+        if (MO.isCPI()) {
+          MO.setIndex(CPE.CPI);
+          break;
+        }
+      // Adjust the refcount of the clone...
+      CPE.RefCount++;
+      // ...and the original.  If we didn't remove the old entry, none of the
+      // addresses changed, so we don't need another pass.
+      return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1;
+    }
+  }
+  return 0;
+}
+
+/// handleConstantPoolUser - Analyze the specified user, checking to see if it
+/// is out-of-range.  If so, pick up the constant pool value and move it some
+/// place in-range.  Return true if we changed any addresses (thus must run
+/// another pass of branch lengthening), false otherwise.
+bool SuperHConstantIslands::handleConstantPoolUser(unsigned CPUserIndex,
+                                                bool CloserWater) {
+  CPUser &U = CPUsers[CPUserIndex];
+  MachineInstr *UserMI = U.MI;
+  MachineInstr *CPEMI  = U.CPEMI;
+  unsigned CPI = getCombinedIndex(CPEMI);
+  unsigned Size = CPEMI->getOperand(2).getImm();
+  // Compute this only once, it's expensive.
+  unsigned UserOffset = getUserOffset(U);
+
+  // See if the current entry is within range, or there is a clone of it
+  // in range.
+  int result = findInRangeCPEntry(U, UserOffset);
+  if (result==1) return false;
+  else if (result==2) return true;
+
+  // No existing clone of this CPE is within range.
+  // We will be generating a new clone.  Get a UID for it.
+  unsigned ID = SFI->createConstIndex();
+
+  // Look for water where we can place this CPE.
+  MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock();
+  MachineBasicBlock *NewMBB;
+  water_iterator IP;
+  if (findAvailableWater(U, UserOffset, IP, CloserWater)) {
+    LLVM_DEBUG(dbgs() << "Found water in range\n");
+    MachineBasicBlock *WaterBB = *IP;
+
+    // If the original WaterList entry was "new water" on this iteration,
+    // propagate that to the new island.  This is just keeping NewWaterList
+    // updated to match the WaterList, which will be updated below.
+    if (NewWaterList.erase(WaterBB))
+      NewWaterList.insert(NewIsland);
+
+    // The new CPE goes before the following block (NewMBB).
+    NewMBB = &*++WaterBB->getIterator();
+  } else {
+    // No water found.
+    LLVM_DEBUG(dbgs() << "No water found\n");
+    createNewWater(CPUserIndex, UserOffset, NewMBB);
+
+    // splitBlockBeforeInstr adds to WaterList, which is important when it is
+    // called while handling branches so that the water will be seen on the
+    // next iteration for constant pools, but in this context, we don't want
+    // it.  Check for this so it will be removed from the WaterList.
+    // Also remove any entry from NewWaterList.
+    MachineBasicBlock *WaterBB = &*--NewMBB->getIterator();
+    IP = find(WaterList, WaterBB);
+    if (IP != WaterList.end())
+      NewWaterList.erase(WaterBB);
+
+    // We are adding new water.  Update NewWaterList.
+    NewWaterList.insert(NewIsland);
+  }
+  // Always align the new block because CP entries can be smaller than 4
+  // bytes. Be careful not to decrease the existing alignment, e.g. NewMBB may
+  // be an already aligned constant pool block.
+  const Align Alignment = Align(4);
+  if (NewMBB->getAlignment() < Alignment)
+    NewMBB->setAlignment(Alignment);
+
+  // Remove the original WaterList entry; we want subsequent insertions in
+  // this vicinity to go after the one we're about to insert.  This
+  // considerably reduces the number of times we have to move the same CPE
+  // more than once and is also important to ensure the algorithm terminates.
+  if (IP != WaterList.end())
+    WaterList.erase(IP);
+
+  // Okay, we know we can put an island before NewMBB now, do it!
+  MF->insert(NewMBB->getIterator(), NewIsland);
+
+  // Update internal data structures to account for the newly inserted MBB.
+  updateForInsertedWaterBlock(NewIsland);
+
+  // Now that we have an island to add the CPE to, clone the original CPE and
+  // add it to the island.
+  U.HighWaterMark = NewIsland;
+  U.CPEMI = BuildMI(NewIsland, DebugLoc(), CPEMI->getDesc())
+                .addImm(ID)
+                .add(CPEMI->getOperand(1))
+                .addImm(Size);
+  CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1));
+
+  // Decrement the old entry, and remove it if refcount becomes 0.
+  decrementCPEReferenceCount(CPI, CPEMI);
+
+  // Mark the basic block as aligned as required by the const-pool entry.
+  NewIsland->setAlignment(getCPEAlign(U.CPEMI));
+
+  // Increase the size of the island block to account for the new entry.
+  BBUtils->adjustBBSize(NewIsland, Size);
+  BBUtils->adjustBBOffsetsAfter(&*--NewIsland->getIterator());
+
+  // Finally, change the CPI in the instruction operand to be ID.
+  for (MachineOperand &MO : UserMI->operands())
+    if (MO.isCPI()) {
+      MO.setIndex(ID);
+      break;
+    }
+
+  LLVM_DEBUG(
+      dbgs() << "  Moved CPE to #" << ID << " CPI=" << CPI
+             << format(" offset=%#x\n",
+                       BBUtils->getBBInfo()[NewIsland->getNumber()].Offset));
+
+  return true;
+}
+
+/// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI,
+/// look up the corresponding CPEntry.
+SuperHConstantIslands::CPEntry *
+SuperHConstantIslands::findConstPoolEntry(unsigned CPI,
+                                       const MachineInstr *CPEMI) {
+  std::vector<CPEntry> &CPEs = CPEntries[CPI];
+  // Number of entries per constpool index should be small, just do a
+  // linear search.
+  for (CPEntry &CPE : CPEs)
+    if (CPE.CPEMI == CPEMI)
+      return &CPE;
+  return nullptr;
+}
+
+/// findAvailableWater - Look for an existing entry in the WaterList in which
+/// we can place the CPE referenced from U so it's within range of U's MI.
+/// Returns true if found, false if not.  If it returns true, WaterIter
+/// is set to the WaterList entry.  For Thumb, prefer water that will not
+/// introduce padding to water that will.  To ensure that this pass
+/// terminates, the CPE location for a particular CPUser is only allowed to
+/// move to a lower address, so search backward from the end of the list and
+/// prefer the first water that is in range.
+bool SuperHConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
+                                            water_iterator &WaterIter,
+                                            bool CloserWater) {
+  if (WaterList.empty())
+    return false;
+
+  unsigned BestGrowth = ~0u;
+  // The nearest water without splitting the UserBB is right after it.
+  // If the distance is still large (we have a big BB), then we need to split it
+  // if we don't converge after certain iterations. This helps the following
+  // situation to converge:
+  //   BB0:
+  //      Big BB
+  //   BB1:
+  //      Constant Pool
+  // When a CP access is out of range, BB0 may be used as water. However,
+  // inserting islands between BB0 and BB1 makes other accesses out of range.
+  MachineBasicBlock *UserBB = U.MI->getParent();
+  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  const Align CPEAlign = getCPEAlign(U.CPEMI);
+  unsigned MinNoSplitDisp = BBInfo[UserBB->getNumber()].postOffset(CPEAlign);
+  if (CloserWater && MinNoSplitDisp > U.getMaxDisp() / 2)
+    return false;
+  for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();;
+       --IP) {
+    MachineBasicBlock* WaterBB = *IP;
+    // Check if water is in range and is either at a lower address than the
+    // current "high water mark" or a new water block that was created since
+    // the previous iteration by inserting an unconditional branch.  In the
+    // latter case, we want to allow resetting the high water mark back to
+    // this new water since we haven't seen it before.  Inserting branches
+    // should be relatively uncommon and when it does happen, we want to be
+    // sure to take advantage of it for all the CPEs near that block, so that
+    // we don't insert more branches than necessary.
+    // When CloserWater is true, we try to find the lowest address after (or
+    // equal to) user MI's BB no matter of padding growth.
+    unsigned Growth;
+    if (isWaterInRange(UserOffset, WaterBB, U, Growth) &&
+        (WaterBB->getNumber() < U.HighWaterMark->getNumber() ||
+         NewWaterList.count(WaterBB) || WaterBB == U.MI->getParent()) &&
+        Growth < BestGrowth) {
+      // This is the least amount of required padding seen so far.
+      BestGrowth = Growth;
+      WaterIter = IP;
+      LLVM_DEBUG(dbgs() << "Found water after " << printMBBReference(*WaterBB)
+                        << " Growth=" << Growth << '\n');
+
+      if (CloserWater && WaterBB == U.MI->getParent())
+        return true;
+      // Keep looking unless it is perfect and we're not looking for the lowest
+      // possible address.
+      if (!CloserWater && BestGrowth == 0)
+        return true;
+    }
+    if (IP == B)
+      break;
+  }
+  return BestGrowth != ~0u;
+}
+
+/// createNewWater - No existing WaterList entry will work for
+/// CPUsers[CPUserIndex], so create a place to put the CPE.  The end of the
+/// block is used if in range, and the conditional branch munged so control
+/// flow is correct.  Otherwise the block is split to create a hole with an
+/// unconditional branch around it.  In either case NewMBB is set to a
+/// block following which the new island can be inserted (the WaterList
+/// is not adjusted).
+void SuperHConstantIslands::createNewWater(unsigned CPUserIndex,
+                                        unsigned UserOffset,
+                                        MachineBasicBlock *&NewMBB) {
+  CPUser &U = CPUsers[CPUserIndex];
+  MachineInstr *UserMI = U.MI;
+  MachineInstr *CPEMI  = U.CPEMI;
+  const Align CPEAlign = getCPEAlign(CPEMI);
+  MachineBasicBlock *UserMBB = UserMI->getParent();
+  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()];
+
+  // If the block does not end in an unconditional branch already, and if the
+  // end of the block is within range, make new water there.  (The addition
+  // below is for the unconditional branch we will be adding: 4 bytes on ARM +
+  // Thumb2, 2 on Thumb1.
+  if (BBHasFallthrough(UserMBB)) {
+    // Size of branch to insert.
+    unsigned Delta = 4;
+    // Compute the offset where the CPE will begin.
+    unsigned CPEOffset = UserBBI.postOffset(CPEAlign) + Delta;
+
+    if (isOffsetInRange(UserOffset, CPEOffset, U)) {
+      LLVM_DEBUG(dbgs() << "Split at end of " << printMBBReference(*UserMBB)
+                        << format(", expected CPE offset %#x\n", CPEOffset));
+      NewMBB = &*++UserMBB->getIterator();
+
+      // Add an unconditional branch from UserMBB to fallthrough block.  Record
+      // it for branch lengthening; this new branch will not get out of range,
+      // but if the preceding conditional branch is out of range, the targets
+      // will be exchanged, and the altered branch may be out of range, so the
+      // machinery has to know about it.
+      BuildMI(UserMBB, DebugLoc(), TII->get(SH::BRA))
+          .addMBB(NewMBB);
+
+      unsigned MaxDisp = getDispRange(SH::BRA);
+      ImmBranches.push_back(ImmBranch(&UserMBB->back(), MaxDisp));
+      BBUtils->computeBlockSize(UserMBB);
+      BBUtils->adjustBBOffsetsAfter(UserMBB);
+      return;
+    }
+  }
+
+  // What a big block.  Find a place within the block to split it.  This is a
+  // little tricky on Thumb1 since instructions are 2 bytes and constant pool
+  // entries are 4 bytes: if instruction I references island CPE, and
+  // instruction I+1 references CPE', it will not work well to put CPE as far
+  // forward as possible, since then CPE' cannot immediately follow it (that
+  // location is 2 bytes farther away from I+1 than CPE was from I) and we'd
+  // need to create a new island.  So, we make a first guess, then walk through
+  // the instructions between the one currently being looked at and the
+  // possible insertion point, and make sure any other instructions that
+  // reference CPEs will be able to use the same island area; if not, we back
+  // up the insertion point.
+
+  // Try to split the block so it's fully aligned.  Compute the latest split
+  // point where we can add a 4-byte branch instruction, and then align to
+  // Align which is the largest possible alignment in the function.
+  const Align Align = MF->getAlignment();
+  assert(Align >= CPEAlign && "Over-aligned constant pool entry");
+  unsigned KnownBits = UserBBI.internalKnownBits();
+  unsigned UPad = UnknownPadding(Align, KnownBits);
+  unsigned BaseInsertOffset = UserOffset + U.getMaxDisp() - UPad;
+  LLVM_DEBUG(dbgs() << format("Split in middle of big block before %#x",
+                              BaseInsertOffset));
+
+  // The 4 in the following is for the unconditional branch we'll be inserting
+  // (allows for long branch on Thumb1).  Alignment of the island is handled
+  // inside isOffsetInRange.
+  BaseInsertOffset -= 4;
+
+  LLVM_DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset)
+                    << " la=" << Log2(Align) << " kb=" << KnownBits
+                    << " up=" << UPad << '\n');
+
+  unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +
+    CPEMI->getOperand(2).getImm();
+  MachineBasicBlock::iterator MI = UserMI;
+  ++MI;
+  unsigned CPUIndex = CPUserIndex+1;
+  unsigned NumCPUsers = CPUsers.size();
+  for (unsigned Offset = UserOffset + TII->getInstSizeInBytes(*UserMI);
+       Offset < BaseInsertOffset;
+       Offset += TII->getInstSizeInBytes(*MI), MI = std::next(MI)) {
+    assert(MI != UserMBB->end() && "Fell off end of block");
+    if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == &*MI) {
+      CPUser &U = CPUsers[CPUIndex];
+      if (!isOffsetInRange(Offset, EndInsertOffset, U)) {
+        // Shift intertion point by one unit of alignment so it is within reach.
+        BaseInsertOffset -= Align.value();
+        EndInsertOffset -= Align.value();
+      }
+      // This is overly conservative, as we don't account for CPEMIs being
+      // reused within the block, but it doesn't matter much.  Also assume CPEs
+      // are added in order with alignment padding.  We may eventually be able
+      // to pack the aligned CPEs better.
+      EndInsertOffset += U.CPEMI->getOperand(2).getImm();
+      CPUIndex++;
+    }
+  }
+
+  --MI;
+
+  // We really must not split an IT block.
+  NewMBB = splitBlockBeforeInstr(&*MI);
+}
+
+/// updateForInsertedWaterBlock - When a block is newly inserted into the
+/// machine function, it upsets all of the block numbers.  Renumber the blocks
+/// and update the arrays that parallel this numbering.
+void SuperHConstantIslands::updateForInsertedWaterBlock(MachineBasicBlock *NewBB) {
+  // Renumber the MBB's to keep them consecutive.
+  NewBB->getParent()->RenumberBlocks(NewBB);
+
+  // Insert an entry into BBInfo to align it properly with the (newly
+  // renumbered) block numbers.
+  BBUtils->insert(NewBB->getNumber(), BasicBlockInfo());
+
+  // Next, update WaterList.  Specifically, we need to add NewMBB as having
+  // available water after it.
+  water_iterator IP = llvm::lower_bound(WaterList, NewBB, CompareMBBNumbers);
+  WaterList.insert(IP, NewBB);
+}
+
+/// Split the basic block containing MI into two blocks, which are joined by
+/// an unconditional branch.  Update data structures and renumber blocks to
+/// account for this change and returns the newly created block.
+MachineBasicBlock *SuperHConstantIslands::splitBlockBeforeInstr(MachineInstr *MI) {
+  MachineBasicBlock *OrigBB = MI->getParent();
+
+  // Collect liveness information at MI.
+  LivePhysRegs LRs(*MF->getSubtarget().getRegisterInfo());
+  LRs.addLiveOuts(*OrigBB);
+  auto LivenessEnd = ++MachineBasicBlock::iterator(MI).getReverse();
+  for (MachineInstr &LiveMI : make_range(OrigBB->rbegin(), LivenessEnd))
+    LRs.stepBackward(LiveMI);
+
+  // Create a new MBB for the code after the OrigBB.
+  MachineBasicBlock *NewBB =
+    MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
+  MachineFunction::iterator MBBI = ++OrigBB->getIterator();
+  MF->insert(MBBI, NewBB);
+
+  // Splice the instructions starting with MI over to NewBB.
+  NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
+
+  // Add an unconditional branch from OrigBB to NewBB.
+  // Note the new unconditional branch is not being recorded.
+  // There doesn't seem to be meaningful DebugInfo available; this doesn't
+  // correspond to anything in the source.
+  BuildMI(OrigBB, DebugLoc(), TII->get(SH::BRA)).addMBB(NewBB);
+
+  // Update the CFG.  All succs of OrigBB are now succs of NewBB.
+  NewBB->transferSuccessors(OrigBB);
+
+  // OrigBB branches to NewBB.
+  OrigBB->addSuccessor(NewBB);
+
+  // Update live-in information in the new block.
+  MachineRegisterInfo &MRI = MF->getRegInfo();
+  for (MCPhysReg L : LRs)
+    if (!MRI.isReserved(L))
+      NewBB->addLiveIn(L);
+
+  // Update internal data structures to account for the newly inserted MBB.
+  // This is almost the same as updateForInsertedWaterBlock, except that
+  // the Water goes after OrigBB, not NewBB.
+  MF->RenumberBlocks(NewBB);
+
+  // Insert an entry into BBInfo to align it properly with the (newly
+  // renumbered) block numbers.
+  BBUtils->insert(NewBB->getNumber(), BasicBlockInfo());
+
+  // Next, update WaterList.  Specifically, we need to add OrigMBB as having
+  // available water after it (but not if it's already there, which happens
+  // when splitting before a conditional branch that is followed by an
+  // unconditional branch - in that case we want to insert NewBB).
+  water_iterator IP = llvm::lower_bound(WaterList, OrigBB, CompareMBBNumbers);
+  MachineBasicBlock* WaterBB = *IP;
+  if (WaterBB == OrigBB)
+    WaterList.insert(std::next(IP), NewBB);
+  else
+    WaterList.insert(IP, OrigBB);
+  NewWaterList.insert(OrigBB);
+
+  // Figure out how large the OrigBB is.  As the first half of the original
+  // block, it cannot contain a tablejump.  The size includes
+  // the new jump we added.  (It should be possible to do this without
+  // recounting everything, but it's very confusing, and this is rarely
+  // executed.)
+  BBUtils->computeBlockSize(OrigBB);
+
+  // Figure out how large the NewMBB is.  As the second half of the original
+  // block, it may contain a tablejump.
+  BBUtils->computeBlockSize(NewBB);
+
+  // All BBOffsets following these blocks must be modified.
+  BBUtils->adjustBBOffsetsAfter(OrigBB);
+
+  return NewBB;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                            CONST PLACEMENT
+//===----------------------------------------------------------------------===//
+
+/// Perform the initial placement of the regular constant pool entries.
+/// To start with, we put them all at the end of the function.
+void
+SuperHConstantIslands::doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs) {
+  
+  // Create the basic block to hold the CPE's.
+  MachineBasicBlock *BB = MF->CreateMachineBasicBlock();
+  MF->push_back(BB);
+
+  // MachineConstantPool measures alignment in bytes.
+  const Align MaxAlign = MCP->getConstantPoolAlign();
+  const unsigned MaxLogAlign = Log2(MaxAlign);
+
+  // Mark the basic block as required by the const-pool.
+  BB->setAlignment(MaxAlign);
+
+  // The function needs to be as aligned as the basic blocks. The linker may
+  // move functions around based on their alignment.
+  // Special case: halfword literals still need word alignment on the function.
+  Align FuncAlign = MaxAlign;
+  if (MaxAlign == 2)
+    FuncAlign = Align(4);
+  MF->ensureAlignment(FuncAlign);
+
+  // Order the entries in BB by descending alignment.  That ensures correct
+  // alignment of all entries as long as BB is sufficiently aligned.  Keep
+  // track of the insertion point for each alignment.  We are going to bucket
+  // sort the entries as they are created.
+  SmallVector<MachineBasicBlock::iterator, 8> InsPoint(MaxLogAlign + 1,
+                                                       BB->end());
+
+  // Add all of the constants from the constant pool to the end block, use an
+  // identity mapping of CPI's to CPE's.
+  const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants();
+
+  const DataLayout &TD = MF->getDataLayout();
+  for (unsigned i = 0, e = CPs.size(); i != e; ++i) {
+    unsigned Size = CPs[i].getSizeInBytes(TD);
+    Align Alignment = CPs[i].getAlign();
+    // Verify that all constant pool entries are a multiple of their alignment.
+    // If not, we would have to pad them out so that instructions stay aligned.
+    assert(isAligned(Alignment, Size) && "CP Entry not multiple of 4 bytes!");
+
+    // Insert CONSTPOOL_ENTRY before entries with a smaller alignment.
+    unsigned LogAlign = Log2(Alignment);
+    MachineBasicBlock::iterator InsAt = InsPoint[LogAlign];
+    MachineInstr *CPEMI =
+      BuildMI(*BB, InsAt, DebugLoc(), TII->get(SH::CONSTPOOL_ENTRY))
+        .addImm(i).addConstantPoolIndex(i).addImm(Size);
+    CPEMIs.push_back(CPEMI);
+
+    // Ensure that future entries with higher alignment get inserted before
+    // CPEMI. This is bucket sort with iterators.
+    for (unsigned a = LogAlign + 1; a <= MaxLogAlign; ++a)
+      if (InsPoint[a] == InsAt)
+        InsPoint[a] = CPEMI;
+
+    // Add a new CPEntry, but no corresponding CPUser yet.
+    CPEntries.emplace_back(1, CPEntry(CPEMI, i));
+    LLVM_DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = "
+                      << Size << ", align = " << Alignment.value() << '\n');
+  }
+  LLVM_DEBUG(BB->dump());
+}
+
+/// fixupImmediateBr - Fix up an immediate branch whose destination is too far
+/// away to fit in its displacement field.
+bool SuperHConstantIslands::fixupImmediateBr(ImmBranch &Br) {
+  MachineInstr *MI = Br.MI;
+  MachineBasicBlock *MBB = MI->getParent();
+  MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
+
+  // Check to see if the DestBB is already in-range.
+  if (BBUtils->isBBInRange(MI, DestBB, Br.MaxDisp))
+    return false;
+
+  // Use BRA to implement far jump.
+  Br.MaxDisp = (1 << 11);
+  MI->setDesc(TII->get(SH::BRA));
+  BBInfoVector &BBInfo = BBUtils->getBBInfo();
+  BBInfo[MBB->getNumber()].Size += 2;
+  BBUtils->adjustBBOffsetsAfter(MBB);
+  return true;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                             INITIALIZATION
+//===----------------------------------------------------------------------===//
+
+/// createARMConstantIslandPass - returns an instance of the constpool
+/// island pass.
+FunctionPass *llvm::createSuperHConstantIslandPass() {
+  return new SuperHConstantIslands();
+}
+
+
+INITIALIZE_PASS(SuperHConstantIslands, "sh-cp-islands", SH_CP_ISLANDS_OPT_NAME,
+                false, false)
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
new file mode 100644
index 0000000000000..0b9d5eaf0701d
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
@@ -0,0 +1,223 @@
+//===- SuperHConstantPoolValue.cpp - SuperH constantpool value --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SuperH specific constantpool value class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperHConstantPoolValue.h"
+
+using namespace llvm;
+
+
+
+//===----------------------------------------------------------------------===//
+// SuperHConstantPoolValue
+//===----------------------------------------------------------------------===//
+
+SuperHConstantPoolValue::SuperHConstantPoolValue(Type *Ty, unsigned id,
+                                           SHCP::SHCPKind kind,
+                                           SHCP::SHCPModifier modifier)
+  : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind), Modifier(modifier) {}
+
+SuperHConstantPoolValue::SuperHConstantPoolValue(LLVMContext &C, unsigned id,
+                                           SHCP::SHCPKind kind,
+                                           SHCP::SHCPModifier modifier)
+  : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)),
+    LabelId(id), Kind(kind), Modifier(modifier) {}
+
+SuperHConstantPoolValue::~SuperHConstantPoolValue() = default;
+
+StringRef SuperHConstantPoolValue::getModifierText() const {
+  switch (Modifier) {
+    // FIXME: Are these case sensitive? It'd be nice to lower-case all the
+    // strings if that's legal.
+  case SHCP::no_modifier:
+    return "none";
+  case SHCP::GOT_PCREL:
+    return "GOT_PCREL";
+  case SHCP::GOT_PLTOFF:
+    return "gotpltoff";
+  case SHCP::DIR:
+    return "";
+  }
+  llvm_unreachable("Unknown modifier!");
+}
+
+int SuperHConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
+                                                    Align Alignment) {
+  llvm_unreachable("Shouldn't be calling this directly!");
+}
+
+void
+SuperHConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
+  ID.AddInteger(LabelId);
+}
+
+bool
+SuperHConstantPoolValue::hasSameValue(SuperHConstantPoolValue *ACPV) {
+  if (ACPV->Kind == Kind &&
+      ACPV->Modifier == Modifier &&
+      ACPV->LabelId == LabelId) {
+
+    // Two PC relative constpool entries containing the same GV address or
+    // external symbols. FIXME: What about blockaddress?
+    if (Kind == SHCP::CPValue || Kind == SHCP::CPExtSymbol)
+      return true;
+  }
+  return false;
+}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void SuperHConstantPoolValue::dump() const {
+  errs() << "  " << *this;
+}
+#endif
+
+void SuperHConstantPoolValue::print(raw_ostream &O) const {
+  if (Modifier) O << "(" << getModifierText() << ")";
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// SuperHConstantPoolConstant
+//===----------------------------------------------------------------------===//
+
+SuperHConstantPoolConstant::SuperHConstantPoolConstant(Type *Ty,
+                                                 const Constant *C,
+                                                 unsigned ID,
+                                                 SHCP::SHCPKind Kind,
+                                                 SHCP::SHCPModifier Modifier)
+  : SuperHConstantPoolValue(Ty, ID, Kind, Modifier),
+    CVal(C) {}
+
+SuperHConstantPoolConstant::SuperHConstantPoolConstant(const Constant *C,
+                                                 unsigned ID,
+                                                 SHCP::SHCPKind Kind,
+                                                 SHCP::SHCPModifier Modifier)
+  : SuperHConstantPoolValue((Type*)C->getType(), ID, Kind, Modifier),
+    CVal(C) {}
+
+SuperHConstantPoolConstant::SuperHConstantPoolConstant(const GlobalVariable *GV,
+                                                 const Constant *C)
+    : SuperHConstantPoolValue((Type *)C->getType(), 0, SHCP::CPPromotedGlobal,
+                           SHCP::no_modifier), CVal(C) {
+  GVars.insert(GV);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID) {
+  return new SuperHConstantPoolConstant(C, ID, SHCP::CPValue,
+                                     SHCP::no_modifier);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const GlobalVariable *GVar,
+                                const Constant *Initializer) {
+  return new SuperHConstantPoolConstant(GVar, Initializer);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const GlobalValue *GV,
+                                SHCP::SHCPModifier Modifier) {
+  return new SuperHConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()),
+                                     GV, 0, SHCP::CPValue,
+                                     Modifier);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID,
+                                SHCP::SHCPKind Kind) {
+  return new SuperHConstantPoolConstant(C, ID, Kind,
+                                     SHCP::no_modifier);
+}
+
+SuperHConstantPoolConstant *
+SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID,
+                                SHCP::SHCPKind Kind,
+                                SHCP::SHCPModifier Modifier) {
+  return new SuperHConstantPoolConstant(C, ID, Kind, Modifier);
+}
+
+const GlobalValue *SuperHConstantPoolConstant::getGV() const {
+  return dyn_cast_or_null<GlobalValue>(CVal);
+}
+
+const BlockAddress *SuperHConstantPoolConstant::getBlockAddress() const {
+  return dyn_cast_or_null<BlockAddress>(CVal);
+}
+
+int SuperHConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
+                                                       Align Alignment) {
+  int index =
+    getExistingMachineCPValueImpl<SuperHConstantPoolConstant>(CP, Alignment);
+  if (index != -1) {
+    auto *CPV = static_cast<SuperHConstantPoolValue*>(
+        CP->getConstants()[index].Val.MachineCPVal);
+    auto *Constant = cast<SuperHConstantPoolConstant>(CPV);
+    Constant->GVars.insert_range(GVars);
+  }
+  return index;
+}
+
+bool SuperHConstantPoolConstant::hasSameValue(SuperHConstantPoolValue *ACPV) {
+  const SuperHConstantPoolConstant *ACPC = dyn_cast<SuperHConstantPoolConstant>(ACPV);
+  return ACPC && ACPC->CVal == CVal && SuperHConstantPoolValue::hasSameValue(ACPV);
+}
+
+void SuperHConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
+  ID.AddPointer(CVal);
+  for (const auto *GV : GVars)
+    ID.AddPointer(GV);
+  SuperHConstantPoolValue::addSelectionDAGCSEId(ID);
+}
+
+void SuperHConstantPoolConstant::print(raw_ostream &O) const {
+  O << CVal->getName();
+  SuperHConstantPoolValue::print(O);
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// SuperHConstantPoolSymbol
+//===----------------------------------------------------------------------===//
+
+SuperHConstantPoolSymbol::SuperHConstantPoolSymbol(LLVMContext &C, StringRef s,
+                                             unsigned id,
+                                             SHCP::SHCPModifier Modifier)
+    : SuperHConstantPoolValue(C, id, SHCP::CPExtSymbol, Modifier),
+      S(std::string(s)) {}
+
+SuperHConstantPoolSymbol *SuperHConstantPoolSymbol::Create(LLVMContext &C,
+                                                     StringRef s, unsigned ID) {
+  return new SuperHConstantPoolSymbol(C, s, ID, SHCP::no_modifier);
+}
+
+int SuperHConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
+                                                     Align Alignment) {
+  return getExistingMachineCPValueImpl<SuperHConstantPoolSymbol>(CP, Alignment);
+}
+
+bool SuperHConstantPoolSymbol::hasSameValue(SuperHConstantPoolValue *SCPV) {
+  const SuperHConstantPoolSymbol *ACPS = dyn_cast<SuperHConstantPoolSymbol>(SCPV);
+  return ACPS && ACPS->S == S && SuperHConstantPoolValue::hasSameValue(SCPV);
+}
+
+void SuperHConstantPoolSymbol::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
+  ID.AddString(S);
+  SuperHConstantPoolValue::addSelectionDAGCSEId(ID);
+}
+
+void SuperHConstantPoolSymbol::print(raw_ostream &O) const {
+  O << S;
+  SuperHConstantPoolValue::print(O);
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
new file mode 100644
index 0000000000000..f606b1b6869b5
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
@@ -0,0 +1,212 @@
+//===- SuperHConstantPoolValue.h - SuperH constantpool value ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SuperH specific constantpool value class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHCONSTANTPOOLVALUE_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHCONSTANTPOOLVALUE_H
+
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/MC/MCSymbol.h"
+
+namespace llvm {
+
+class BlockAddress;
+class Constant;
+class GlobalValue;
+class GlobalVariable;
+class LLVMContext;
+class MachineBasicBlock;
+class raw_ostream;
+class Type;
+
+namespace SHCP {
+
+  enum SHCPKind {
+    CPValue,
+    CPExtSymbol,
+    CPBlockAddress,
+    CPMachineBasicBlock,
+    CPPromotedGlobal
+  };
+
+  enum SHCPModifier {
+    no_modifier,  /// None
+    DIR,          /// Direct
+    GOT_PCREL,    /// Global Offset Table, PC Relative
+    GOT_PLTOFF,   /// Global Offset Table, Thread Pointer Offset
+  };
+
+} // end namespace SHCP
+
+class SuperHConstantPoolValue : public MachineConstantPoolValue {
+  unsigned LabelId;           // Label id of the load.
+  SHCP::SHCPKind Kind;      // Kind of constant.
+  SHCP::SHCPModifier Modifier;  // GV modifier i.e. (&GV(modifier)-(LPIC+8))
+protected:
+  SuperHConstantPoolValue(Type *Ty, unsigned id, SHCP::SHCPKind Kind, 
+                          SHCP::SHCPModifier Modifier);
+
+  SuperHConstantPoolValue(LLVMContext &C, unsigned id, SHCP::SHCPKind Kind,
+                          SHCP::SHCPModifier Modifier);
+
+  template <typename Derived>
+  int getExistingMachineCPValueImpl(MachineConstantPool *CP, Align Alignment) {
+    const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
+    for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
+      if (Constants[i].isMachineConstantPoolEntry() &&
+          Constants[i].getAlign() >= Alignment) {
+        auto *CPV =
+          static_cast<SuperHConstantPoolValue*>(Constants[i].Val.MachineCPVal);
+        if (Derived *APC = dyn_cast<Derived>(CPV))
+          if (cast<Derived>(this)->equals(APC))
+            return i;
+      }
+    }
+
+    return -1;
+  }
+
+public:
+  ~SuperHConstantPoolValue() override;
+
+  SHCP::SHCPKind getKind() const { return Kind; }
+  SHCP::SHCPModifier getModifier() const { return Modifier; }
+  StringRef getModifierText() const;
+  bool hasModifier() const { return Modifier != SHCP::no_modifier; }
+
+  unsigned getLabelId() const { return LabelId; }
+
+  bool isGlobalValue() const { return Kind == SHCP::CPValue; }
+  bool isExtSymbol() const { return Kind == SHCP::CPExtSymbol; }
+  bool isBlockAddress() const { return Kind == SHCP::CPBlockAddress; }
+  bool isMachineBasicBlock() const{ return Kind == SHCP::CPMachineBasicBlock; }
+  bool isPromotedGlobal() const{ return Kind == SHCP::CPPromotedGlobal; }
+
+  int getExistingMachineCPValue(MachineConstantPool *CP,
+                                Align Alignment) override;
+
+  void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
+
+  /// hasSameValue - Return true if this ARM constpool value can share the same
+  /// constantpool entry as another ARM constpool value.
+  virtual bool hasSameValue(SuperHConstantPoolValue *ACPV);
+
+  bool equals(const SuperHConstantPoolValue *A) const {
+    return this->LabelId == A->LabelId &&
+      this->Modifier == A->Modifier;
+  }
+
+  void print(raw_ostream &O) const override;
+  void print(raw_ostream *O) const { if (O) print(*O); }
+  void dump() const;
+};
+
+inline raw_ostream &operator<<(raw_ostream &O, const SuperHConstantPoolValue &V) {
+  V.print(O);
+  return O;
+}
+
+
+/// SuperHConstantPoolConstant - SuperH-specific constant pool values for Constants,
+/// Functions, and BlockAddresses.
+class SuperHConstantPoolConstant : public SuperHConstantPoolValue {
+  const Constant *CVal;         // Constant being loaded.
+  SmallPtrSet<const GlobalVariable*, 1> GVars;
+
+  SuperHConstantPoolConstant(const Constant *C,
+                             unsigned ID,
+                             SHCP::SHCPKind Kind,
+                             SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant(Type *Ty, const Constant *C,
+                             unsigned ID,
+                             SHCP::SHCPKind Kind,
+                             SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant(const GlobalVariable *GV, const Constant *Init);
+
+public:
+  static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID);
+  static SuperHConstantPoolConstant *Create(const GlobalValue *GV,
+                                         SHCP::SHCPModifier Modifier);
+  static SuperHConstantPoolConstant *Create(const GlobalVariable *GV,
+                                         const Constant *Initializer);
+  static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID,
+                                         SHCP::SHCPKind Kind);
+  static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID,
+                                         SHCP::SHCPKind Kind,
+                                         SHCP::SHCPModifier Modifier);
+
+  const GlobalValue *getGV() const;
+  const BlockAddress *getBlockAddress() const;
+
+  using promoted_iterator = SmallPtrSet<const GlobalVariable *, 1>::iterator;
+
+  iterator_range<promoted_iterator> promotedGlobals() { return GVars; }
+
+  const Constant *getPromotedGlobalInit() const {
+    return CVal;
+  }
+
+  int getExistingMachineCPValue(MachineConstantPool *CP,
+                                Align Alignment) override;
+
+  /// hasSameValue - Return true if this ARM constpool value can share the same
+  /// constantpool entry as another ARM constpool value.
+  bool hasSameValue(SuperHConstantPoolValue *ACPV) override;
+
+  void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
+
+  void print(raw_ostream &O) const override;
+
+  static bool classof(const SuperHConstantPoolValue *APV) {
+    return APV->isGlobalValue() || APV->isBlockAddress() ||
+           APV->isPromotedGlobal();
+  }
+
+  bool equals(const SuperHConstantPoolConstant *A) const {
+    return CVal == A->CVal && SuperHConstantPoolValue::equals(A);
+  }
+};
+
+/// SuperHConstantPoolSymbol - SH-specific constantpool 
+/// values for external symbols.
+class SuperHConstantPoolSymbol : public SuperHConstantPoolValue {
+  const std::string S;          // ExtSymbol being loaded.
+
+  SuperHConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id, SHCP::SHCPModifier Modifier);
+
+public:
+  static SuperHConstantPoolSymbol *Create(LLVMContext &C, StringRef s, unsigned ID);
+
+  StringRef getSymbol() const { return S; }
+
+  int getExistingMachineCPValue(MachineConstantPool *CP,
+                                Align Alignment) override;
+
+  void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
+
+  /// hasSameValue - Return true if this ARM constpool value can share the same
+  /// constantpool entry as another ARM constpool value.
+  bool hasSameValue(SuperHConstantPoolValue *SCPV) override;
+
+  void print(raw_ostream &O) const override;
+
+  static bool classof(const SuperHConstantPoolValue *SCPV) {
+    return SCPV->isExtSymbol();
+  }
+
+  bool equals(const SuperHConstantPoolSymbol *A) const {
+    return S == A->S && SuperHConstantPoolValue::equals(A);
+  }
+};
+
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 9f7bacb1c92b5..8d092e0b570aa 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -51,39 +51,91 @@ class SuperHFillDelaySlots : public MachineFunctionPass {
   bool expandMI(Block &MBB, BlockIt MBBI);
 
   // Expansion functions
+  MachineInstr *findSlotCandidate(Block &MBB, BlockIt MBBI);
   bool fillDelaySlot(Block &MBB, BlockIt MBBI);
 };
 
 } // end namespace
 
 
-bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
+
+
+//===----------------------------------------------------------------------===//
+//                                Expansions
+//===----------------------------------------------------------------------===//
+
+// Walks backwards through the basic block to find a candidate that is eligible
+// for filling delay slots.
+MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI) {
   MachineInstr &MI = *MBBI;
+
+
+  // TODO:  Make this a while loop that keeps a list of "used" registers
+  //        by instructions.
   if (auto *Prev = MBBI->getPrevNode()) {
+    unsigned Opcode = Prev->getOpcode();
+
+    // If we encounter a branch instruction, then it's no longer safe to
+    // move the instruction down.
+    if (Prev->isBranch() || Prev->isCall() || Prev->isReturn()) 
+      return nullptr;
+
+    // NOTE:  RTS has an extra constraint that it cannot have
+    //        lds @r15+,PR or equivalent in its delay slot.
+    if (MI.isReturn()) {
+      
+      // Skip the LDS instruction.
+      if (Opcode == SH::LDSLRminciPR || Opcode == SH::LDSRmPR)
+        return nullptr;
+    }
 
-    // If the prior instruction is capable of filling the delay slot
-    // swap the 2 instructions.
-    if (TII->canFillDelaySlot(Prev->getOpcode())) {
-      LDBG() << "Swapping " << TII->getName(MI.getOpcode()) 
-             << " and " << TII->getName(Prev->getOpcode()) 
-             << " @ " << MBB.getParent()->getName();
-      MBB.insertAfter(MBBI, Prev->removeFromParent());
-      return true;
+    // NOTE:  Conditional branches can't have their condition code set
+    //        in the delay slot. As such, if the previous instruction
+    //        implicitly defines the status register, assume that the 
+    //        T bit was set.
+    if (MI.isConditionalBranch()) {
+      if (Prev->definesRegister(SH::SR, TRI))
+        return nullptr;
+    }
+
+    // Otherwise, select this instruction if can fill a delay slot,
+    // has no prior node, or the prior node is not a delay slot.
+    if (TII->canFillDelaySlot(Opcode)) {
+      if (!Prev->getPrevNode() || !Prev->getPrevNode()->hasDelaySlot())
+        return Prev;
     }
   }
 
-  LDBG() << "Inserting NOP after " << TII->getName(MI.getOpcode())
-         << " @ " << MBB.getParent()->getName();
+  return nullptr;
+}
+
+// Finds and fills delay slots of instructions in a basic block.
+bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
+  MachineFunction &MF = *MBB.getParent();
+  MachineInstr &MI = *MBBI;
+
+  if (auto *Candidate = SuperHFillDelaySlots::findSlotCandidate(MBB, MBBI)) {
+      LLVM_DEBUG(dbgs() << "Swapping " << TII->getName(MI.getOpcode()) 
+                        << " and " << TII->getName(Candidate->getOpcode()) 
+                        << " @ " << MBB.getParent()->getName() << "\n");
+
+      MBB.insertAfter(MBBI, Candidate->removeFromParent());
+      return true;
+  }
+
+  LLVM_DEBUG(dbgs() << "Inserting NOP after " << TII->getName(MI.getOpcode())
+                    << " @ " << MBB.getParent()->getName() << "\n");
 
   // Otherwise just insert a NOP.
-  BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(SH::NOP));
+  MBB.insertAfter(MBBI, MF.CreateMachineInstr(TII->get(SH::NOP), MI.getDebugLoc())); 
   return true;
 }
 
 
 
+
 //===----------------------------------------------------------------------===//
-//                                HELPERS
+//                                Helpers
 //===----------------------------------------------------------------------===//
 
 bool SuperHFillDelaySlots::expandMI(Block &MBB, BlockIt MBBI) {
@@ -109,6 +161,8 @@ bool SuperHFillDelaySlots::expandMBB(Block &MBB) {
 }
 
 bool SuperHFillDelaySlots::runOnMachineFunction(MachineFunction &MF) {
+  LLVM_DEBUG(dbgs() << "\n********** SuperHFillDelaySlots **********\n");
+
   bool Modified = false;
 
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 4d11c6e99983c..93baa923182da 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -17,15 +17,22 @@
 #include "SuperHInstrInfo.h"
 #include "SuperHRegisterInfo.h"
 #include "SuperHSubtarget.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCRegister.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/DebugLog.h"
 #include "llvm/Target/TargetMachine.h"
 
 #define DEBUG_TYPE "sh-framelowering"
 
+static cl::opt<bool>
+AccumOutgoingArgs("sh-accumulate-outgoing-args", cl::Hidden, cl::init(false),
+          cl::desc("Reserve space for outgoing arguments in the function prologue."));
+
 using namespace llvm;
 
 // Get amount of times to shift the value in a SP adjustment
@@ -57,8 +64,8 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
     // Fast path, emit a single immediate add.
     //    Emit add #-(size),r15
     BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
-      .addImm((int)AdjValue)
-      .addReg(SP);
+      .addReg(SP)
+      .addImm((int)AdjValue);
 
     return true;
   }
@@ -106,51 +113,82 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   const SuperHInstrInfo &TII = *STI.getInstrInfo();
   const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+  const MCContext &Ctx = MF.getContext();
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
   bool HasFP = hasFP(MF);
 
   Register SP = RII.getStackRegister();
   Register FP = RII.getFrameRegister();
+  Register GOT = RII.getGOTRegister();
 
-  LDBG() << "emitPrologue";
+  // Early exit if we have no frame pointer.
+  if (!HasFP) {
+    return;
+  }
 
   // Realign stack
   uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
   MFI.setStackSize(StackSize);
+  
+  if (STI.isPositionIndependent()) {
+    // Position Independent Prologue
+
+    // 1. Store GOT to stack and load local GOT.
+    if (auto *GOTSym = MF.getPICBaseSymbol()) {
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+        .addReg(GOT)
+        .setMIFlag(MachineInstr::FrameSetup);
+    }
+
+    // 2. Establish Stack Frame
+    //    mov.l r14, at -r15
+    //    add <stackadj>,r15
+    //    mov r15,r14
+    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), FP)
+      .addReg(SP)
+      .setMIFlag(MachineInstr::FrameSetup);
+    emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
+    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), SP)
+      .addReg(FP)
+      .setMIFlag(MachineInstr::FrameSetup);
 
-  // 1. Create stack frame
-  emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
-
-  // TODO: Create working register set.
+    // 4. Save return address to stack.
+    if (MFI.hasCalls()) {
+      BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameSetup);
+    }
 
-  // 3. Save return address to stack.
-  BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
-    .addReg(SP)
-    .setMIFlag(MachineInstr::FrameSetup);
+  } else {
+    // Position Dependent Prologue
 
-  // 4. Establish frame pointer
-  if (HasFP) {
-    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
-      .addReg(SP)
+    // 1. Establish Frame Pointer
+    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+      .addReg(FP)
       .setMIFlag(MachineInstr::FrameSetup);
-  }
 
-  // TODO: Establish GCP?
+    // 2. Create new stack frame
+    emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
+
+    // 3. Save return address to stack.
+    if (MFI.hasCalls()) {
+      BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameSetup);
+    }
+  }
 }
 
 void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
   const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
   Register SP = RII.getStackRegister();
   Register FP = RII.getFrameRegister();
-  
-  LDBG() << "emitEpilogue";
 
   // Early exit if we have no frame pointer.
   if (!hasFP(MF)) {
     return;
   }
 
-
   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   DebugLoc DL = MBBI->getDebugLoc();
@@ -159,16 +197,79 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
 
   uint32_t StackSize = MFI.getStackSize();
 
-  // TODO: Restore callee save registers
+  if (STI.isPositionIndependent()) {
 
-  // 2. Restore return address from stack
-  BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
-    .addReg(SP)
-    .setMIFlag(MachineInstr::FrameDestroy);
+    // 1. Restore return address from stack.
+    if (MFI.hasCalls()) {
+      BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameDestroy);
+    }
+
+    // 2. Delete stack frame, restoring stack pointer.
+    if (StackSize > 0)
+      emitSPAdj(MF, MBB, MBBI, StackSize);
+
+  } else {
+
+    // 1. Restore return address from stack.
+    if (MFI.hasCalls()) {
+      BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameDestroy);
+    }
 
-  // 3. Delete stack frame, restoring stack pointer.
-  if (StackSize > 0)
-    emitSPAdj(MF, MBB, MBBI, StackSize);
+    // 2. Delete stack frame, restoring stack pointer.
+    if (StackSize > 0)
+      emitSPAdj(MF, MBB, MBBI, StackSize);
+  }
+}
+bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+                                 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+  
+  if (CSI.empty()) {
+    return false;
+  }
+
+  DebugLoc DL = MBB.findDebugLoc(MI);
+  MachineFunction &MF = *MBB.getParent();
+  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+  const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+  const TargetInstrInfo &TII = *STI.getInstrInfo();
+  Register SP = RII.getStackRegister();
+
+  for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
+    MCRegister Reg = I.getReg();
+    BuildMI(MBB, MI, DL, TII.get(SH::MOVLRmRndeci), SP)
+      .addReg(Reg)
+      .setMIFlag(MachineInstr::FrameSetup);
+  }
+
+  return true;
+}
+
+bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+                                   MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+  
+  if (CSI.empty()) {
+      return false;
+  }
+
+  DebugLoc DL = MBB.findDebugLoc(MI);
+  MachineFunction &MF = *MBB.getParent();
+  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+  const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+  const TargetInstrInfo &TII = *STI.getInstrInfo();
+  Register SP = RII.getStackRegister();
+
+  for (const CalleeSavedInfo &I : CSI) {
+    MCRegister Reg = I.getReg();
+    BuildMI(MBB, MI, DL, TII.get(SH::MOVLRminciRn), SP)
+      .addReg(Reg)
+      .setMIFlag(MachineInstr::FrameDestroy);
+  }
+
+  return true;
 }
 
 MachineBasicBlock::iterator
@@ -178,8 +279,6 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   const SuperHInstrInfo &TII = *STI.getInstrInfo();
 
-  LDBG() << "eliminateCallFramePseudoInstr";
-
   // If call frame is reserved, erase.
   if (hasReservedCallFrame(MF)) {
     return MBB.erase(MI);
@@ -194,16 +293,21 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
   DebugLoc DL = MI->getDebugLoc();
   unsigned int Opcode = MI->getOpcode();
   if (Opcode == TII.getCallFrameSetupOpcode()) {
-    LDBG() << "eliminateCallFramePseudoInstr->CallFrameSetup";
+
   } else {
-    LDBG() << "eliminateCallFramePseudoInstr->CallFrameDestroy";
     assert(Opcode == TII.getCallFrameDestroyOpcode());
-
   }
 
   return MBB.erase(MI);
 }
 
+bool SuperHFrameLowering::canSimplifyCallFramePseudos(
+    const MachineFunction &MF) const {
+  // Always simplify call frame pseudo instructions, even when
+  // hasReservedCallFrame is false.
+  return true;
+}
+
 bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   return MF.getTarget().Options.DisableFramePointerElim(MF) ||
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index dd2cc63aaa32e..7a20234e7817c 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -31,11 +31,16 @@ class SuperHFrameLowering : public TargetFrameLowering {
                           /*LocalAreaOffset*/0,
                           /*TransAl*/Align(4)),
       STI(STI) {}
+  bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
+  bool hasReservedCallFrame(const MachineFunction &MF) const override;
 
   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
-
-  bool hasReservedCallFrame(const MachineFunction &MF) const override;
+  bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+                                 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
+  bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+                                   MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
+  
   MachineBasicBlock::iterator
   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
                                 MachineBasicBlock::iterator I) const override;
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index badd48f1df62a..3b9e745b8d334 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -11,7 +11,11 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "MCTargetDesc/SuperHBaseInfo.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperH.h"
+#include "SuperHConstantPoolValue.h"
+#include "SuperHMachineFunctionInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
 #include "SuperHSelectionDAGInfo.h"
@@ -19,15 +23,45 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/DebugLog.h"
 
 #define DEBUG_TYPE "sh-isel"
 #define PASS_NAME "SH DAG->DAG Instruction Selection"
 
+static cl::opt<bool>
+CBranchForceDelaySlot("sh-cbranch-force-delay-slot", cl::Hidden, cl::init(false),
+          cl::desc("Force the usage of delay slots for conditional branches."));
+
 using namespace llvm;
 
 namespace {
 
+struct SHAddressWrapper {
+  enum SHAddrType {
+    GLOBAL_VALUE,
+    CONSTANT,
+    BLOCK,
+    SYM_LOCAL,
+    SYM_EXTERNAL,
+  };
+  SHAddrType Type;
+  SDValue BaseReg;
+  int64_t Disp;
+
+  // Max size of displacement.
+  unsigned DispSize;
+
+  const GlobalValue *GV;
+  const Constant *CP;
+  const BlockAddress *BlockAddr;
+  const char *ES;
+  MCSymbol *MCSym;
+  SHRefClass SymbolFlags; // SHII::MO_*
+
+  SHAddressWrapper(unsigned DS) : DispSize(DS) { }
+};
+
 /// Lowers LLVM IR (in DAG form) to SuperH MC instructions (in DAG form).
 class SuperHDAGToDAGISel : public SelectionDAGISel {
 public:
@@ -40,7 +74,26 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
   bool SelectInlineAsmMemoryOperand(const SDValue &Op,
                                     InlineAsm::ConstraintCode ConstraintCode,
                                     std::vector<SDValue> &OutOps) override;
-  bool SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValue Rhs);
+  
+  bool SelectAddr(SDNode *Root, SDValue N, SDValue &Base, SDValue &Disp);
+
+
+  /// Return a target constant with the specified value of type i4.
+  inline SDValue getI4Imm(int64_t Imm, const SDLoc &DL) {
+    return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i4);
+  }
+
+
+  /// Return a target constant with the specified value of type i8.
+  inline SDValue getI8Imm(int64_t Imm, const SDLoc &DL) {
+    return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i8);
+  }
+
+
+  /// Return a target constant with the specified value of type i16.
+  inline SDValue getI16Imm(int64_t Imm, const SDLoc &DL) {
+    return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i16);
+  }
 
 // Include the pieces autogenerated from the target description.
 #include "SuperHGenDAGISel.inc"
@@ -49,10 +102,13 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
   void Select(SDNode *N) override;
 
   bool trySelect(SDNode *N);
-  bool trySelectRET(SDNode *N);
   bool trySelectSDIV(SDNode *N);
   bool trySelectUDIV(SDNode *N);
   bool trySelectFrameIndex(SDNode *N);
+  bool trySelectWrapper(SDNode *N);
+  bool trySelectCMP(SDNode *N);
+  bool trySelectBrcond(SDNode *N);
+  bool trySelectSELECT_CC(SDNode *N);
 
   const SuperHSubtarget *Subtarget;
 };
@@ -81,11 +137,158 @@ bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
 }
 
 
+
+
 //===----------------------------------------------------------------------===//
-//                              Address Lowering
+//                             Address Lowering
 //===----------------------------------------------------------------------===//
 
-bool SuperHDAGToDAGISel::SelectAddr(SDNode *Root, SDValue N, SDValue Lhs, SDValue Rhs) {
+bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
+  auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
+  auto DL = SDLoc(N);
+
+  MachineFunction &MF = CurDAG->getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+  SDValue N0 = N->getOperand(0);
+
+  // Global Addresses
+  if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+    ReplaceNode(N, Res);
+    return true;
+  }
+
+  // External Symbols
+  if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+    ReplaceNode(N, Res);
+    return true;
+  }
+
+  // Block Addresses
+  if (auto *CPV = SFI->tryGetConstant((BlockAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+    ReplaceNode(N, Res);
+    return true;
+  }
+
+  return false;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                          Conditionals Lowering
+//===----------------------------------------------------------------------===//
+
+bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
+  SDValue LHS = N->getOperand(0);
+  SDValue RHS = N->getOperand(1);
+  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+  SDLoc DL(N);
+
+  // NOTE:  The comparisons just set the T bit, it's up to later instructions
+  //        to interpret the T bit as positive or negative.
+  SDNode *Res = nullptr;
+  switch(CC) {
+  default: break;
+  case ISD::SETEQ:
+  case ISD::SETNE: {
+
+    // TST would be faster in this case.
+    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
+      if (C->getSExtValue() == 0) {
+        Res = CurDAG->getMachineNode(SH::TSTRmRn, DL, MVT::i32, LHS, LHS);
+        break;
+      }
+    }
+    Res = CurDAG->getMachineNode(SH::CMPEQRmRn, DL, MVT::i32, LHS, RHS);
+    break;
+  }
+  case ISD::SETUGE:
+  case ISD::SETULT: {
+    Res = CurDAG->getMachineNode(SH::CMPHSRmRn, DL, MVT::i32, LHS, RHS);
+    break;
+  }
+  case ISD::SETOGE:
+  case ISD::SETOLT: {
+    Res = CurDAG->getMachineNode(SH::CMPGERmRn, DL, MVT::i32, LHS, RHS);
+    break;
+  }
+  case ISD::SETUGT:
+  case ISD::SETULE: {
+    Res = CurDAG->getMachineNode(SH::CMPGTRmRn, DL, MVT::i32, LHS, RHS);
+    break;
+  }
+  case ISD::SETOGT:
+  case ISD::SETOLE: {
+    Res = CurDAG->getMachineNode(SH::CMPHIRmRn, DL, MVT::i32, LHS, RHS);
+    break;
+  }
+  }
+
+  if (Res) {
+    ReplaceUses(SDValue(N, 0), SDValue(Res, 0));
+    CurDAG->RemoveDeadNode(N);
+    return true;
+  }
+
+  return false;
+}
+
+bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
+  SDValue Chain = N->getOperand(0);
+  SDValue Dest = N->getOperand(1);
+  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+  SDValue Cmp = N->getOperand(3);
+  SDLoc DL(N);
+
+  // NOTE:  The CMP instruction writes implicitly to the T bit of the status
+  //        register, as such, we need to add said copy to our chain to ensure
+  //        scheduling can handle it.
+  Chain = CurDAG->getCopyToReg(Chain, DL, SH::SR, Cmp, SDValue());
+
+  // NOTE:  The comparisons just set the T bit, it's up to later instructions
+  //        to interpret the T bit as positive or negative.
+  MachineSDNode *Res = nullptr;
+  switch(CC) {
+  default: break;
+  case ISD::SETEQ:
+  case ISD::SETUGE:
+  case ISD::SETOGE:
+  case ISD::SETUGT:
+  case ISD::SETOGT:
+    Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BTS : SH::BT, 
+          DL, MVT::Other, Dest, Chain);
+    break;
+  case ISD::SETNE:
+  case ISD::SETULE:
+  case ISD::SETOLE:
+  case ISD::SETULT:
+  case ISD::SETOLT:
+    Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BFS : SH::BF, 
+          DL, MVT::Other, Dest, Chain);
+    break;
+  }
+
+  if (Res) {
+    ReplaceUses(SDValue(N, 0), SDValue(Res, 0));
+    CurDAG->RemoveDeadNode(N);
+    return true;
+  }
+
+  return false;
+}
+
+bool SuperHDAGToDAGISel::trySelectSELECT_CC(SDNode *N) {
+  const SDValue &TrueV = N->getOperand(0);
+  const SDValue &FalseV = N->getOperand(1);
+  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+  const SDValue &Cmp = N->getOperand(3);
   return false;
 }
 
@@ -107,20 +310,48 @@ bool SuperHDAGToDAGISel::trySelectFrameIndex(SDNode *N) {
   return true;
 }
 
+
+
+
+//===----------------------------------------------------------------------===//
+//                             Selection Code
+//===----------------------------------------------------------------------===//
+
 bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
   unsigned Opcode = N->getOpcode();
+  SDLoc DL(N);
+
   switch(Opcode) {
+  case ISD::GLOBAL_OFFSET_TABLE: {
+    SDValue GOT = CurDAG->getTargetExternalSymbol(
+        "_GLOBAL_OFFSET_TABLE_", MVT::i32, SHII::MO_GOTPC);
+    MachineSDNode *Res = 
+        CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, GOT);
+    ReplaceNode(N, Res);
+    return true;
+  }
   case ISD::FrameIndex:
     return trySelectFrameIndex(N);
+  case SHISD::WRAPPER:
+    return trySelectWrapper(N);
+  case SHISD::CMP:
+    return trySelectCMP(N);
+  case SHISD::SELECT_CC:
+    return trySelectSELECT_CC(N);
+  case SHISD::BRCOND:
+    return trySelectBrcond(N);
   default:
     return false;
   }
 }
 
 void SuperHDAGToDAGISel::Select(SDNode *N) {
+
+  LLVM_DEBUG(dbgs() << "SH: Selecting "; N->dump(CurDAG); dbgs() << '\n');
   
   // Node was already selected?
   if (N->isMachineOpcode()) {
+    LLVM_DEBUG(dbgs() << "== "; N->dump(CurDAG); dbgs() << '\n');
     N->setNodeId(-1);
     return;
   }
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 39304e493a23d..59b297b48f886 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -12,23 +12,31 @@
 //===-----------------------------------------------------------------------===//
 
 #include "SuperHISelLowering.h"
+#include "SuperHConstantPoolValue.h"
+#include "SuperHMachineFunctionInfo.h"
 #include "SuperHSelectionDAGInfo.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
 #include "SuperHRegisterInfo.h"
+#include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/DebugLog.h"
 
 using namespace llvm;
 
 #define DEBUG_TYPE "sh-lower"
 
+#define DEBUG_FN_PRINT() LDBG() << __PRETTY_FUNCTION__;
+
 static bool RetCC_SuperH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
                                CCValAssign::LocInfo &LocInfo,
                                ISD::ArgFlagsTy &ArgFlags, CCState &State) {
@@ -47,12 +55,15 @@ static bool RetCC_SuperH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
                                            const SuperHSubtarget &STI)
     : TargetLowering(TM, STI), Subtarget(&STI) {
+  auto *RegInfo = Subtarget->getRegisterInfo();
 
   // GPR Registers are always 32 bit on SuperH.
   addRegisterClass(MVT::i32, &SH::GPRRegClass);
+  computeRegisterProperties(Subtarget->getRegisterInfo());
+
   setSchedulingPreference(Sched::RegPressure);
   setSupportsUnalignedAtomics(false);
-  computeRegisterProperties(Subtarget->getRegisterInfo());
+  setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
 
   // Loads and stores are legal
   for (MVT VT : MVT::integer_valuetypes()) {
@@ -72,14 +83,154 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::SREM, VT, Custom);
   }
 
+  setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
+  setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
+  setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
+  setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
+
+
+  setOperationAction(ISD::BR_CC, MVT::i8, Custom);
+  setOperationAction(ISD::BR_CC, MVT::i16, Custom);
+  setOperationAction(ISD::BR_CC, MVT::i32, Custom);
+  setOperationAction(ISD::BR_CC, MVT::i64, Custom);
+  setOperationAction(ISD::BRCOND, MVT::Other, Expand);
+
+  setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
+  setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
+  setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
+  setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
+  setOperationAction(ISD::SETCC, MVT::i8, Custom);
+  setOperationAction(ISD::SETCC, MVT::i16, Custom);
+  setOperationAction(ISD::SETCC, MVT::i32, Custom);
+  setOperationAction(ISD::SETCC, MVT::i64, Custom);
 
   setBooleanContents(ZeroOrOneBooleanContent);
   setBooleanVectorContents(ZeroOrOneBooleanContent);
-  setStackPointerRegisterToSaveRestore(SH::GBR);
-  setJumpIsExpensive(true);
+  setJumpIsExpensive(false);
   setMinFunctionAlignment(Align(4));
 }
 
+
+
+
+//===----------------------------------------------------------------------===//
+//                        CONDITIONAL BRANCH LOWERING
+//===----------------------------------------------------------------------===//
+SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
+                                       SDValue &OutCC, SelectionDAG &DAG, SDLoc DL) const {
+  OutCC = DAG.getCondCode(CC);
+  return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, OutCC);
+}
+
+SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
+  SDValue LHS = Op.getOperand(0);
+  SDValue RHS = Op.getOperand(1);
+  SDValue TrueV = Op.getOperand(2);
+  SDValue FalseV = Op.getOperand(3);
+  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
+  SDLoc DL(Op);
+
+  SDValue TargetCC;
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+
+  SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
+  return DAG.getNode(SHISD::SELECT_CC, DL, Op.getValueType(), Ops);
+  
+}
+
+SDValue SuperHTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
+  SDValue LHS = Op.getOperand(0);
+  SDValue RHS = Op.getOperand(1);
+  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
+  SDLoc DL(Op);
+
+  SDValue TargetCC;
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+
+  SDValue TrueV = DAG.getConstant(1, DL, Op.getValueType());
+  SDValue FalseV = DAG.getConstant(0, DL, Op.getValueType());
+  SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
+  return DAG.getNode(SHISD::SELECT_CC, DL, Op.getValueType(), Ops);
+}
+
+SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
+  DEBUG_FN_PRINT()
+
+  SDValue Chain = Op.getOperand(0);
+  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
+  SDValue LHS = Op.getOperand(2);
+  SDValue RHS = Op.getOperand(3);
+  SDValue Dest = Op.getOperand(4);
+  SDLoc DL(Op);
+
+  SDValue TargetCC;
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+  return DAG.getNode(SHISD::BRCOND, DL, MVT::Other, Chain, Dest, TargetCC, Cmp);
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                             ADDRESS LOWERING
+//===----------------------------------------------------------------------===//
+
+SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const {
+  DEBUG_FN_PRINT()
+
+  // Get the address of the target into a register
+  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Op)) {
+    auto PtrVT = getPointerTy(DAG.getDataLayout());
+    auto DL = SDLoc(G);
+
+    SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
+    SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, OpFlags);
+    return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
+  }
+  return SDValue();
+}
+
+SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const {
+  DEBUG_FN_PRINT()
+
+  // Get the address of the target into a register
+  if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Op)) {
+    auto PtrVT = getPointerTy(DAG.getDataLayout());
+    auto DL = SDLoc(S);
+
+    const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
+    SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
+
+    SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags);
+    return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
+  }
+  return SDValue();
+}
+
+SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
+  DEBUG_FN_PRINT()
+
+  // Get the address of the target into a register
+  if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) {
+    auto PtrVT = getPointerTy(DAG.getDataLayout());
+    auto DL = SDLoc(BA);
+
+    const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
+    SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
+
+    SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT, OpFlags);
+    return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
+  }
+  return SDValue();
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                             ARGUMENT LOWERING
+//===----------------------------------------------------------------------===//
+
 SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
                        CallingConv::ID CallConv, bool IsVarArg,
                        const SmallVectorImpl<ISD::InputArg> &Ins,
@@ -158,6 +309,7 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
 
 
 
+
 //===----------------------------------------------------------------------===//
 //                              RETURN LOWERING
 //===----------------------------------------------------------------------===//
@@ -209,6 +361,12 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
   return DAG.getNode(SHISD::RET_GLUE, dl, MVT::Other, RetOps);
 }
 
+SDValue SuperHTargetLowering::getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const {
+  return DAG.getRegister(Subtarget->getRegisterInfo()->getGOTRegister(),
+                         getPointerTy(DAG.getDataLayout()));
+}
+
+
 
 
 
@@ -217,6 +375,7 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
 //===----------------------------------------------------------------------===//
 
 SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const {
+  const SuperHRegisterInfo &RI = *Subtarget->getRegisterInfo();
   SelectionDAG &DAG = CLI.DAG;
   MachineFunction &MF = DAG.getMachineFunction();
   SDLoc &DL = CLI.DL;
@@ -225,40 +384,24 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
   SDValue Chain = CLI.Chain;
   SDValue Callee = CLI.Callee;
-  bool &isTailCall = CLI.IsTailCall;
+  bool &IsTailCall = CLI.IsTailCall;
   CallingConv::ID CallConv = CLI.CallConv;
-  bool isVarArg = CLI.IsVarArg;
+  bool IsVarArg = CLI.IsVarArg;
 
   // TODO: This was all yoinked from AVR, it likely needs to be modified to fit the calling
   // convention of SuperH.
 
   // Tail Call Optimisation not supported yet.
-  isTailCall = false;
-  isVarArg = false;
-
-  // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
-  // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
-  // node so that legalize doesn't hack it.
-  const Function *F = nullptr;
-  if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
-    const GlobalValue *GV = G->getGlobal();
-    if (isa<Function>(GV))
-      F = cast<Function>(GV);
-    Callee =
-        DAG.getTargetGlobalAddress(GV, DL, getPointerTy(DAG.getDataLayout()));
-  } else if (const ExternalSymbolSDNode *ES =
-                 dyn_cast<ExternalSymbolSDNode>(Callee)) {
-    Callee = DAG.getTargetExternalSymbol(ES->getSymbol(),
-                                         getPointerTy(DAG.getDataLayout()));
-  }
+  IsTailCall = false;
+  IsVarArg = false;
 
-  if (isVarArg) {
+  if (IsVarArg) {
     return Chain;
   }
 
   // Analyze operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
-  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
+  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
                  *DAG.getContext());
 
   // Get a count of how many bytes are to be pushed on the stack.
@@ -324,8 +467,15 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
     InGlue = Chain.getValue(1);
   }
 
+  // Resolve the global value to jump to.
+  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+    Callee = LowerGlobalAddress(SDValue(G, 0), DAG);
+  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
+    Callee = LowerExternalSymbol(SDValue(S, 0), DAG);
+  }
+  InGlue = Chain.getValue(1);
+
   // Returns a chain & a flag for retval copy to use.
-  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
   SmallVector<SDValue, 8> Ops;
   Ops.push_back(Chain);
   Ops.push_back(Callee);
@@ -336,10 +486,6 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
   }
 
-  // The zero register (usually R1) must be passed as an implicit register so
-  // that this register is correctly zeroed in interrupts.
-  Ops.push_back(DAG.getRegister(SH::R0, MVT::i32));
-
   // Add a register mask operand representing the call-preserved registers.
   const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
   const uint32_t *Mask =
@@ -351,7 +497,7 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
     Ops.push_back(InGlue);
   }
 
-  Chain = DAG.getNode(SHISD::CALL, DL, NodeTys, Ops);
+  Chain = DAG.getNode(SHISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
   InGlue = Chain.getValue(1);
 
   // Create the CALLSEQ_END node.
@@ -361,17 +507,17 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
     InGlue = Chain.getValue(1);
   }
 
-  return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, DL, DAG, InVals);
+  return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG, InVals);
 }
 
 SDValue SuperHTargetLowering::LowerCallResult(
-    SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
+    SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
 
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RVLocs;
-  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
+  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
                  *DAG.getContext());
 
   // Handle runtime calling convs.
@@ -465,6 +611,18 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
   case ISD::UDIV:
   case ISD::SDIV:
     return LowerDiv(Op, DAG);
+  case ISD::GlobalAddress:
+    return LowerGlobalAddress(Op, DAG);
+  case ISD::ExternalSymbol:
+    return LowerExternalSymbol(Op, DAG);
+  case ISD::BlockAddress:
+    return LowerBlockAddress(Op, DAG);
+  case ISD::SETCC:
+    return LowerBR_CC(Op, DAG);
+  case ISD::SELECT_CC:
+    return LowerBR_CC(Op, DAG);
+  case ISD::BR_CC:
+    return LowerBR_CC(Op, DAG);
   }
   return SDValue();
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index e23143b989fe5..ffdc90b53afc1 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -15,14 +15,34 @@
 #define LLVM_LIB_TARGET_SUPERH_SUPERHISELLOWERING_H
 
 #include "SuperH.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
 
 namespace llvm {
 class SuperHSubtarget;
+class MachineConstantPool;
 
 class SuperHTargetLowering : public TargetLowering  {
   const SuperHSubtarget *Subtarget;
 
+public:
+  SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
+
+  // LowerToConstantPool - SuperH's compressed instruction set means that 
+  // immediates and displacements can not be larger than 8 bits. 
+  // As such we need to store said immediates and displacements within 
+  // constants that are within range of the program counter.
+  //
+  // As such this function is a helper that:
+  //  1. Allocates a constant pool slot for the address
+  //  2. Inserts the target address into said slot.
+  //  3. Returns the neccesary, but non-legalized instruction sequence to fetch
+  //     the address from that constant pool slot.
+  template<class NodeTy>
+  SDValue LowerToConstantPool(NodeTy* N, SelectionDAG &DAG) const;
+
   SDValue LowerFormalArguments(SDValue Chain,
                          CallingConv::ID CallConv, bool IsVarArg,
                          const SmallVectorImpl<ISD::InputArg> &Ins,
@@ -40,15 +60,27 @@ class SuperHTargetLowering : public TargetLowering  {
               SmallVectorImpl<SDValue> &/*InVals*/) const override;
 
   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
-
-  // Custom Lowerings
+  
+  // Lowerings
+  SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerDiv(SDValue Op, SelectionDAG &DAG) const;
+
+  SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
+  SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &OutCC,
+                   SelectionDAG &DAG, SDLoc DL) const;
+private:
+
+  SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override;
+
+  // Lowerings
   SDValue LowerCallResult(
     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const;
-public:
-  SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index b5015c9e8dc63..07523d475b3c5 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -15,14 +15,21 @@
 #include "SuperHRegisterInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
+#include "MCTargetDesc/SuperHInstPrinter.h"
 #include "SuperH.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
 
 using namespace llvm;
 
@@ -35,32 +42,200 @@ SuperHInstrInfo::SuperHInstrInfo(const SuperHSubtarget &ST)
     : SuperHGenInstrInfo(ST, RI, SH::ADJCALLSTACKDOWN, SH::ADJCALLSTACKUP),
       RI(ST), Subtarget(ST) { }
 
+
+
+// Gets whether a given opcode can fill a delay slot.
+// 
+// SuperH does not allow branch instructions of any kind to be situated 
+// in a delay slot, nor does it allow instructions with delay slots
+// to be chained together.
+bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
+  auto Desc = this->get(Opcode);
+  return !Desc.hasDelaySlot() && 
+         !Desc.isBranch() && 
+         !Desc.isCall() && !Desc.isReturn() &&
+         !(Desc.TSFlags & 0x1);
+}
+
+/// Return the noop instruction to use for a noop.
+MCInst SuperHInstrInfo::getNop() const {
+  MCInst I = MCInst();
+  I.setOpcode(SH::NOP);
+  return I;
+}
+
+void SuperHInstrInfo::insertNoop(MachineBasicBlock &MBB, 
+                                 MachineBasicBlock::iterator MI) const {
+  BuildMI(&MBB, MI->getDebugLoc(), get(SH::NOP));
+}
+
+ISD::CondCode SuperHInstrInfo::getCondFromBranchOp(unsigned Op) const {
+  switch (Op) {
+  default:
+    return ISD::SETFALSE;
+  case SH::BRA:
+  case SH::NOP:
+    return ISD::SETTRUE;
+  case SH::BT:
+  case SH::BTS:
+    return ISD::SETEQ;
+  case SH::BF:
+  case SH::BFS:
+    return ISD::SETNE;
+  }
+}
+
+const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
+  switch (CC) {
+  default:
+    llvm_unreachable("Unknown condition code!");
+  case ISD::SETEQ:
+  case ISD::SETGE:
+  case ISD::SETGT:
+    return get(SH::BT);
+  case ISD::SETNE:
+  case ISD::SETLE:
+  case ISD::SETLT:
+    return get(SH::BF);
+  }
+}
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                              Stack Frames
+//===----------------------------------------------------------------------===//
+
 void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                            MachineBasicBlock::iterator MI, const DebugLoc &DL,
                            Register DestReg, Register SrcReg, bool KillSrc,
                            bool RenamableDest,
                            bool RenamableSrc) const {
 
+  // Do nothing, self copy.
+  if (SrcReg == DestReg)
+    return;
+
   // If the targets are GPR registers, use MOV Rm, Rn.
   if (SH::GPRRegClass.contains(DestReg, SrcReg)) {
     BuildMI(MBB, MI, DL, get(SH::MOVRmRn), DestReg)
       .addReg(SrcReg, getKillRegState(KillSrc));
     return;
-  }
+  };
 
   // Otherwise this is not possible.
   llvm_unreachable("Impossible reg-to-reg copy");
 }
 
-// Gets whether a given opcode can fill a delay slot.
-// 
-// SuperH does not allow branch instructions of any kind to be situated 
-// in a delay slot, nor does it allow instructions with delay slots
-// to be chained together.
-bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
-  auto Desc = this->get(Opcode);
-  return !Desc.hasDelaySlot() && 
-         !Desc.isBranch() && 
-         !Desc.isCall() && !Desc.isReturn() &&
-         !(Desc.TSFlags & 0x1);
-}
\ No newline at end of file
+
+
+
+//===----------------------------------------------------------------------===//
+//                              Branch Analysis
+//===----------------------------------------------------------------------===//
+
+bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+                   MachineBasicBlock *&FBB,
+                   SmallVectorImpl<MachineOperand> &Cond,
+                   bool AllowModify) const {
+  // Start from the bottom of the block and work up, examining the
+  // terminator instructions.
+  MachineBasicBlock::iterator I = MBB.end();
+  MachineBasicBlock::iterator UnCondBrIter = MBB.end();
+
+  while (I != MBB.begin()) {
+    --I;
+    if (I->isDebugInstr()) {
+      continue;
+    }
+
+    LLVM_DEBUG(dbgs() << "analyzeBranch " << getName(I->getOpcode()) << "\n");
+
+    // Working from the bottom, when we see a non-terminator
+    // instruction, we're done.
+    if (!isUnpredicatedTerminator(*I)) {
+      break;
+    }
+
+    // Handle unconditional branches.
+    if (I->getOpcode() == SH::BRA) {
+      UnCondBrIter = I;
+
+      if (!AllowModify) {
+        TBB = I->getOperand(0).getMBB();
+        continue;
+      }
+
+      // If the block has any instructions after a BRA, delete them.
+      MBB.erase(std::next(I), MBB.end());
+      Cond.clear();
+      FBB = nullptr;
+
+      // Delete the BRA if it's equivalent to a fall-through.
+      if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
+        TBB = nullptr;
+        I->eraseFromParent();
+        I = MBB.end();
+        UnCondBrIter = MBB.end();
+        continue;
+      }
+
+      // TBB is used to indicate the unconditinal destination.
+      TBB = I->getOperand(0).getMBB();
+      continue;
+    }
+  }
+
+  return false;
+}
+
+unsigned SuperHInstrInfo::insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+                      MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
+                      const DebugLoc &DL,
+                      int *BytesAdded) const {
+  return 0;
+}
+
+unsigned SuperHInstrInfo::removeBranch(MachineBasicBlock &MBB,
+                      int *BytesRemoved) const {
+  return 0;
+}
+
+bool
+SuperHInstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+
+}
+
+MachineBasicBlock *SuperHInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
+  if (MI.isBranch())
+    return MI.getOperand(0).getMBB();
+
+  llvm_unreachable("unimplemented branch instructions");
+}
+
+bool SuperHInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
+                           int64_t BrOffset) const {
+  switch (BranchOp) {
+  default:
+    llvm_unreachable("unexpected opcode!");
+  case SH::BF:
+  case SH::BT:
+  case SH::BFS:
+  case SH::BTS:
+  case SH::BRA:
+    return isIntN(8, BrOffset);
+  case SH::BSR:
+    return isIntN(12, BrOffset);
+  }
+}
+
+void SuperHInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
+                          MachineBasicBlock &NewDestBB,
+                          MachineBasicBlock &RestoreBB, const DebugLoc &DL,
+                          int64_t BrOffset, RegScavenger *RS) const {
+
+}
+
+
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 78e9d10ae445c..3b309249c8b22 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -35,13 +35,53 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   /// always be able to get register info as well (through this method).
   const SuperHRegisterInfo &getRegisterInfo() const { return RI; }
 
+  /// Gets whether a given opcode can fill a delay slot.
+  /// 
+  /// SuperH does not allow branch instructions of any kind to be situated 
+  /// in a delay slot, nor does it allow instructions with delay slots
+  /// to be chained together.
+  bool canFillDelaySlot(unsigned Opcode) const;
+  ISD::CondCode getCondFromBranchOp(unsigned Op) const;
+  const MCInstrDesc &getBrCond(ISD::CondCode CC) const;
+
+  // Instruction Info
+
+  /// Return the noop instruction to use for a noop.
+  MCInst getNop() const override;
+  void insertNoop(MachineBasicBlock &MBB, 
+                  MachineBasicBlock::iterator MI) const override;
+
+
+  // Stack Frames
   void copyPhysReg(MachineBasicBlock &MBB,
                            MachineBasicBlock::iterator MI, const DebugLoc &DL,
                            Register DestReg, Register SrcReg, bool KillSrc,
                            bool RenamableDest = false,
                            bool RenamableSrc = false) const override;
 
-  bool canFillDelaySlot(unsigned Opcode) const;
+  // Branch Analysis
+  bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+                     MachineBasicBlock *&FBB,
+                     SmallVectorImpl<MachineOperand> &Cond,
+                     bool AllowModify = false) const override;
+  unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+                        MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
+                        const DebugLoc &DL,
+                        int *BytesAdded = nullptr) const override;
+  unsigned removeBranch(MachineBasicBlock &MBB,
+                        int *BytesRemoved = nullptr) const override;
+  bool
+  reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
+
+  MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
+
+  bool isBranchOffsetInRange(unsigned BranchOpc,
+                             int64_t BrOffset) const override;
+
+  void insertIndirectBranch(MachineBasicBlock &MBB,
+                            MachineBasicBlock &NewDestBB,
+                            MachineBasicBlock &RestoreBB, const DebugLoc &DL,
+                            int64_t BrOffset, RegScavenger *RS) const override;
 };
 
 const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 3d7303b507dbd..deff63e16f00b 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -46,8 +46,14 @@ def ptr_op : RegisterOperand<sh_ptr_rc> {
 //===--------------------------------------------------------------------------===//
 
 def SHSDT_CallSeqStart  : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
-def SHSDT_CallSeqEnd  : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
-def SHSDT_Call        : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
+def SHSDT_CallSeqEnd    : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+def SHSDT_Call          : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
+def SHSDT_PICAdd        : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
+                                          SDTCisPtrTy<1>, SDTCisVT<2, i32>]>;
+def SHSDT_Brcond        : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisInt<1>]>;
+def SHSDT_Cmp           : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisInt<2>]>;
+def SHSDT_SelectCC      : SDTypeProfile<1, 3,
+                          [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisInt<3>]>;
 
 //===--------------------------------------------------------------------------===//
 // SuperH Specific Nodes
@@ -67,6 +73,15 @@ def SHRetGlue       : SDNode<"SHISD::RET_GLUE", SDTNone,
                             [SDNPHasChain, SDNPOptInGlue, 
                              SDNPVariadic]>;
 
+def SHWrapper       : SDNode<"SHISD::WRAPPER", SDTIntUnaryOp>;
+def SHPICAdd        : SDNode<"SHISD::PIC_ADD", SHSDT_PICAdd>;
+
+// Conditional Branching and Comparison
+def SHselectcc      : SDNode<"SHISD::SELECT_CC", SHSDT_SelectCC, [SDNPInGlue]>;
+def SHbrcond        : SDNode<"SHISD::BRCOND", SHSDT_Brcond, [SDNPHasChain, SDNPInGlue]>;
+def SHcmp           : SDNode<"SHISD::CMP", SHSDT_Cmp, [SDNPOutGlue]>;
+
+
 //===--------------------------------------------------------------------------===//
 // Operand Classes
 //===--------------------------------------------------------------------------===//
@@ -126,7 +141,17 @@ def disp4   : SHDispOp<4, i4>;
 def disp8   : SHDispOp<8, i8>;
 def disp12  : SHDispOp<12, i16>;
 
+def brtarget       : Operand<OtherVT> {
+  let EncoderMethod = "getBranchTargetOpValue";
+  let DecoderMethod = "DecodeBranchTarget";
+  let PrintMethod = "printPCRelImm";
+  let OperandType = "OPERAND_PCREL";
+}
 
+// An operand for the CONSTPOOL_ENTRY pseudo-instruction.
+def cpinst_operand : Operand<i32> {
+  let PrintMethod = "printCPInstOperand";
+}
 
 // Memory
 class SHMemRegOp<RegisterClass regClass> 
@@ -136,38 +161,6 @@ class SHMemRegOp<RegisterClass regClass>
 }
 def GPRMem : SHMemRegOp<GPR>;
 
-// Memory Indirect (Register + Register)
-def MemRRI : Operand<iPTR> {
-  let ParserMatchClass = SHMemClass;
-  let OperandType = "OPERAND_MEMORY";
-  let MIOperandInfo = (ops GPR, GPR);
-}
-
-// Memory Indirect (Register + Disp)
-def MemRD : Operand<iPTR> {
-  let ParserMatchClass = SHMemClass;
-  let OperandType = "OPERAND_MEMORY";
-  let MIOperandInfo = (ops GPR, disp8);
-}
-
-// Memory Indirect (GBR + disp)
-def MemGBRI : Operand<iPTR> {
-  let ParserMatchClass = SHMemClass;
-  let OperandType = "OPERAND_MEMORY";
-  let MIOperandInfo = (ops R_GBR, disp8);
-}
-
-// Memory Indirect (R0 + disp)
-def MemR0I : Operand<iPTR> {
-  let ParserMatchClass = SHMemClass;
-  let OperandType = "OPERAND_MEMORY";
-  let MIOperandInfo = (ops R_R0, disp8);
-}
-
-// Addressing mode pattern reg+disp
-let WantsRoot = true in
-def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
-
 //===--------------------------------------------------------------------------===//
 // Predicates
 //===--------------------------------------------------------------------------===//
@@ -228,26 +221,26 @@ def MOVI8Rn       : InstRnI8<0b1110000000000000,
                             "mov #$imm,$Rn",
                             [(set i32:$Rn, imm8:$imm)]>;
 
-// mov @(disp, PC), R0
+// mova @(disp, PC), R0
 let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
 def MOVAD8PCR0      : InstD8<0b1100011100000000,
                             (outs), (ins disp8:$disp),
-                            "mov @($disp,PC),R0",
-                            []>;
+                            "mova @($disp,PC),R0",
+                            [(set R0, (load disp8:$disp))]>;
 
 // mov.w @(disp,PC), Rn 
 let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
 def MOVWD8PCRn    : InstRnD8<0b1001000000000000,
                             (outs GPR:$Rn), (ins disp8:$disp),
                             "mov.w @($disp,PC),$Rn",
-                            [(set i32:$Rn, (sextloadi16 addr:$disp))]>;
+                            [(set i32:$Rn, (sextloadi16 disp8:$disp))]>;
 
 // mov.l @(disp,PC), Rn 
 let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
 def MOVLD8PCRn    : InstRnD8<0b1101000000000000,
                             (outs GPR:$Rn), (ins disp8:$disp),
                             "mov.l @($disp,PC),$Rn",
-                            [(set i32:$Rn, (load addr:$disp))]>;
+                            [(set i32:$Rn, (load disp8:$disp))]>;
 
 // movt Rn
 def MOVTRn          : InstRn<0b0000000000101001,
@@ -490,7 +483,6 @@ let hasSideEffects = 0, mayStore = 1 in {
 
 
 
-
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 //                            Arithmetic Instructions
@@ -506,17 +498,16 @@ let hasSideEffects = 0, mayStore = 1 in {
 let hasSideEffects = 0, Constraints = "$src = $Rn" in {
   
   // add Rm, Rn
-  let isCommutable = 1 in
   def ADDRmRn       : InstRmRn<0b0011000000001100, 
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "add $Rm,$Rn",
                               [(set i32:$Rn, (add i32:$Rm, i32:$src))]>;
   
   // add imm:8, Rn
-  def ADDI8Rn       : InstRnI8<0b0011000000001100, 
-                              (outs GPR:$Rn), (ins imm8:$imm, GPR:$src),
+  def ADDI8Rn       : InstRnI8<0b0111000000000000, 
+                              (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
                               "add #$imm,$Rn",
-                              [(set i32:$Rn, (add imm8:$imm, i32:$src))]>;
+                              [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
 
   // addc Rm, Rn
   let Defs = [SR], Uses = [SR], isCommutable = 1 in
@@ -723,69 +714,64 @@ def CMPSTRRmRn      : InstRmRn<0b0010000000001100,
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
+// and Rm,Rn
+let Constraints = "$src = $Rn" in
+def ANDRmRn       : InstRmRn<0b0010000000001001, 
+                            (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                            "and $Rm,$Rn",
+                            [(set i32:$Rn, (and i32:$Rm, i32:$src))]>;
+// and #imm,R0
+let Defs = [R0], Uses = [R0] in
+def ANDI8R0         : InstI8<0b1100100100000000, 
+                            (outs), (ins imm8:$imm),
+                            "and #$imm,R0",
+                            []>;
 
-let hasSideEffects = 0 in {
-
-  // and Rm,Rn
-  let Constraints = "$src = $Rn" in
-  def ANDRmRn       : InstRmRn<0b0010000000001001, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
-                              "and $Rm,$Rn",
-                              []>;
-  // and #imm,R0
-  let Defs = [R0], Uses = [R0] in
-  def ANDI8R0         : InstI8<0b1100100100000000, 
-                              (outs), (ins imm8:$imm),
-                              "and #$imm,R0",
-                              []>;
-
-  // not Rm,Rn
-  let Constraints = "$src = $Rn" in
-  def NOTRmRn       : InstRmRn<0b0110000000000111, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
-                              "not $Rm,$Rn",
-                              []>;
-
-  // or Rm,Rn
-  let Constraints = "$src = $Rn" in
-  def ORRmRn        : InstRmRn<0b0010000000001011, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
-                              "or $Rm,$Rn",
-                              []>;
-  // or #imm,R0
-  let Defs = [R0], Uses = [R0] in
-  def ORI8R0          : InstI8<0b1100101100000000, 
-                              (outs), (ins imm8:$imm),
-                              "or #$imm,R0",
-                              []>;
+// not Rm,Rn
+def NOTRmRn       : InstRmRn<0b0110000000000111, 
+                            (outs GPR:$Rn), (ins GPR:$Rm),
+                            "not $Rm,$Rn",
+                            [(set i32:$Rn, (not i32:$Rm))]>;
+
+// or Rm,Rn
+let Constraints = "$src = $Rn" in
+def ORRmRn        : InstRmRn<0b0010000000001011, 
+                            (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                            "or $Rm,$Rn",
+                            [(set i32:$Rn, (or i32:$Rm, i32:$src))]>;
+// or #imm,R0
+let Defs = [R0], Uses = [R0] in
+def ORI8R0          : InstI8<0b1100101100000000, 
+                            (outs), (ins imm8:$imm),
+                            "or #$imm,R0",
+                            []>;
 
-  // xor Rm,Rn
-  let Constraints = "$src = $Rn" in
-  def XORRmRn       : InstRmRn<0b0010000000001010, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
-                              "xor $Rm,$Rn",
-                              []>;
-  // xor #imm,R0
-  let Defs = [R0], Uses = [R0] in
-  def XORI8R0         : InstI8<0b1100101000000000, 
-                              (outs), (ins imm8:$imm),
-                              "xor #$imm,R0",
-                              []>;
+// xor Rm,Rn
+let Constraints = "$src = $Rn" in
+def XORRmRn       : InstRmRn<0b0010000000001010, 
+                            (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                            "xor $Rm,$Rn",
+                            [(set i32:$Rn, (xor i32:$Rm, i32:$src))]>;
+// xor #imm,R0
+let Defs = [R0], Uses = [R0] in
+def XORI8R0         : InstI8<0b1100101000000000, 
+                            (outs), (ins imm8:$imm),
+                            "xor #$imm,R0",
+                            []>;
 
-  // tst Rm,Rn
-  let Defs = [SR], Constraints = "$src = $Rn" in
-  def TSTRmRn       : InstRmRn<0b0010000000001000, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
-                              "tst $Rm,$Rn",
-                              []>;
-  // tst #imm,R0
-  let Defs = [R0, SR], Uses = [R0] in
-  def TSTI8R0         : InstI8<0b1100100000000000, 
-                              (outs), (ins imm8:$imm),
-                              "tst #$imm,R0",
-                              []>;
+// tst Rm,Rn
+let Defs = [SR] in
+def TSTRmRn       : InstRmRn<0b0010000000001000, 
+                            (outs), (ins GPR:$Rm, GPR:$Rn),
+                            "tst $Rm,$Rn",
+                            []>;
+// tst #imm,R0
+let Defs = [SR], Uses = [R0] in
+def TSTI8R0         : InstI8<0b1100100000000000, 
+                            (outs), (ins imm8:$imm),
+                            "tst #$imm,R0",
+                            []>;
 
-}
 
 
 
@@ -817,14 +803,14 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
   def ROTLRn          : InstRn<0b0100000000000100, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "rotl $Rn",
-                              []>;
+                              [(set i32:$Rn, (rotl i32:$src, (i8 1)))]>;
 
   // rotr Rn
   let Defs = [SR] in
   def ROTRRn          : InstRn<0b0100000000000101, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "rotr $Rn",
-                              []>;
+                              [(set i32:$Rn, (rotr i32:$src, (i8 1)))]>;
 
   // shal Rn
   let Defs = [SR] in
@@ -838,58 +824,58 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
   def SHARRn          : InstRn<0b0100000000100001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shar $Rn",
-                              []>;
+                              [(set i32:$Rn, (sra i32:$src, (i8 1)))]>;
 
   // shll Rn
   let Defs = [SR] in
   def SHLLRn          : InstRn<0b0100000000000000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll $Rn",
-                              []>;
+                              [(set i32:$Rn, (shl i32:$src, (i8 1)))]>;
 
   // shll2 Rn
   let Defs = [SR] in
   def SHLL2Rn          : InstRn<0b0100000000001000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll2 $Rn",
-                              []>;
+                              [(set i32:$Rn, (shl i32:$src, (i8 2)))]>;
 
   // shll8 Rn
   def SHLL8Rn          : InstRn<0b0100000000011000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll8 $Rn",
-                              []>;
+                              [(set i32:$Rn, (shl i32:$src, (i8 8)))]>;
 
   // shll16 Rn
   def SHLL16Rn          : InstRn<0b0100000000101000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll16 $Rn",
-                              []>;
+                              [(set i32:$Rn, (shl i32:$src, (i8 16)))]>;
 
   // shlr Rn
   let Defs = [SR] in
   def SHLRRn          : InstRn<0b0100000000000001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr $Rn",
-                              []>;
+                              [(set i32:$Rn, (srl i32:$src, (i8 1)))]>;
 
   // shlr2 Rn
   def SHLR2Rn          : InstRn<0b0100000000001001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr2 $Rn",
-                              []>;
+                              [(set i32:$Rn, (srl i32:$src, (i8 2)))]>;
 
   // shlr8 Rn
   def SHLR8Rn          : InstRn<0b0100000000011001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr8 $Rn",
-                              []>;
+                              [(set i32:$Rn, (srl i32:$src, (i8 8)))]>;
 
   // shlr16 Rn
   def SHLR16Rn          : InstRn<0b0100000000101001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr16 $Rn",
-                              []>;
+                              [(set i32:$Rn, (srl i32:$src, (i8 16)))]>;
 
 }
 
@@ -900,24 +886,70 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
-// TODO: Port these to the updated way.
-// def BF_Disp      : BrOp_Disp8<0b1000101100000000, "bf">;
-// def BFS_Disp    : BrOpD_Disp8<0b1000111100000000, "bf/s">;
-// def BT_Disp      : BrOp_Disp8<0b1000100100000000, "bt">;
-// def BTS_Disp    : BrOpD_Disp8<0b1000110100000000, "bt/s">;
-// def BRA_Disp    : BrOp_Disp12<0b1010000000000000, "bra">;
-// def BRAF_Rm         : BrOp_Rm<0b0000000000100011, "braf">;
-// def BSR_Disp    : BrOp_Disp12<0b1011000000000000, "bsr">;
-// def BSRF_Rm         : BrOp_Rm<0b0000000000000011, "bsrf">;
-// def JMP_Rmi        : BrOp_Rmi<0b0100000000101011, "jmp">;
+let isTerminator = 1 in {
+  let isBranch = 1, Uses = [SR] in
+  def BF              : InstD8<0b1000101100000000, 
+                              (outs), (ins brtarget:$disp),
+                              "bf $disp",
+                              []>;
+
+  let isBranch = 1, hasDelaySlot = 1, Uses = [SR] in
+  def BFS             : InstD8<0b1000111100000000, 
+                              (outs), (ins brtarget:$disp),
+                              "bf/s $disp",
+                              []>;
+
+  let isBranch = 1, Uses = [SR] in
+  def BT              : InstD8<0b1000100100000000, 
+                              (outs), (ins brtarget:$disp),
+                              "bt $disp",
+                              []>;
+
+  let isBranch = 1, hasDelaySlot = 1, Uses = [SR] in
+  def BTS             : InstD8<0b1000110100000000, 
+                              (outs), (ins brtarget:$disp),
+                              "bt/s $disp",
+                              []>;
+
+  let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+  def BRA            : InstD12<0b1010000000000000, 
+                              (outs), (ins brtarget:$disp),
+                              "bra $disp",
+                              [(br bb:$disp)]>;
+
+  let isIndirectBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+  def BRAF            : InstRm<0b0000000000100011, 
+                              (outs), (ins GPR:$Rm),
+                              "braf $Rm",
+                              []>;
+
+  let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+  def BSR            : InstD12<0b1011000000000000, 
+                              (outs), (ins brtarget:$disp),
+                              "bsr $disp",
+                              []>;
+
+  let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+  def BSRF            : InstRm<0b0000000000000011, 
+                              (outs), (ins GPR:$Rm),
+                              "bsrf $Rm",
+                              []>;
+
+  let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
+  def JMP             : InstRm<0b0100000000101011, 
+                              (outs), (ins GPR:$Rm),
+                              "jmp @$Rm",
+                              []>;
+}
+
 
 
 //===--------------------------------------------------------------------------===//
 // Call Instructions
 //===--------------------------------------------------------------------------===//
 
-let isCall = 1, hasDelaySlot = 1 in {
-  let Uses = [GBR] in
+let isCall = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in {
+  let Uses = [SR, GBR] in
   def JSRRmi          : InstRm<0b0100000000001011,
                               (outs), (ins GPRMem:$Rm),
                               "jsr @$Rm",
@@ -925,6 +957,9 @@ let isCall = 1, hasDelaySlot = 1 in {
 }
 
 
+
+
+
 //===--------------------------------------------------------------------------===//
 // Return Instructions
 //===--------------------------------------------------------------------------===//
@@ -1038,7 +1073,7 @@ def LDSLRminciPR      : InstRm<0b0100000000100110,
                               []>;
 
 // nop
-let hasSideEffects = 1 in
+let hasSideEffects = 1, isTerminator = 1 in
 def NOP                 : Inst<0b0000000000001001, (outs), (ins), "nop", []>;
 
 // rte
@@ -1164,9 +1199,6 @@ include "SuperHInstrDSP.td"
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
-
-
-
 //===--------------------------------------------------------------------------===//
 // Stack Frame
 //===--------------------------------------------------------------------------===//
@@ -1176,6 +1208,15 @@ include "SuperHInstrDSP.td"
 let Defs = [SR], hasSideEffects = 0 in
 def SHFrmIdx : SHPseudo<(outs GPR:$dst), (ins GPR:$src, disp12:$src2)>;
 
+/// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in
+/// the function.  The first operand is the ID# for this instruction, the second
+/// is the index into the MachineConstantPool that this is, the third is the
+/// size in bytes of this constant pool entry.
+let hasSideEffects = 0, isNotDuplicable = 1, hasNoSchedulingInfo = 1 in
+def CONSTPOOL_ENTRY : SHPseudo<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size), 
+                              "!CONSTPOOL_ENTRY $instid, $cpidx, $size",
+                              []>;
+
 let Defs = [R0], Uses = [R0] in {
 def ADJCALLSTACKDOWN : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
                                "!ADJCALLSTACKDOWN $amt1, $amt2",
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index 9e3198be7dddd..d5b7cc883b51f 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "SuperHMCInstLower.h"
+#include "MCTargetDesc/SuperHMCAsmInfo.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
 #include "SuperHSubtarget.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/MC/MCExpr.h"
@@ -18,7 +20,32 @@ namespace llvm {
 MCOperand
 SuperHMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
                                       const SuperHSubtarget &Subtarget) const {
-  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
+  const MCExpr *Expr = nullptr;
+  switch (MO.getTargetFlags()) {
+    case SHII::MO_NO_FLAG:
+      Expr = MCSymbolRefExpr::create(Sym, SH::S_None, Ctx);
+      break;
+
+    case SHII::MO_GOT:
+      Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT, Ctx);
+      break;
+
+    case SHII::MO_GOTPC:
+      Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_PCREL, Ctx);
+      break;
+
+    case SHII::MO_GOTOFF:
+      Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_OFF, Ctx);
+      break;
+
+    case SHII::MO_DIR:
+      Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
+      break;
+
+    case SHII::MO_PCREL:
+      Expr = MCSymbolRefExpr::create(Sym, SH::S_PCREL, Ctx);
+      break;
+  }
   return MCOperand::createExpr(Expr);
 }
 
@@ -52,6 +79,11 @@ void SuperHMCInstLower::lowerInstruction(const MachineInstr &MI,
           MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()), Subtarget);
       break;
     case MachineOperand::MO_MachineBasicBlock:
+
+      // NOTE:  Branch instructions will generally jump to labels.
+      //        so ensure we emit them if they're referenced in an
+      //        operand during lowering.
+      MO.getMBB()->setLabelMustBeEmitted();
       MCOp = MCOperand::createExpr(
           MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
       break;
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
new file mode 100644
index 0000000000000..880835ebafc49
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -0,0 +1,126 @@
+//===-- SuperHMachineFunctionInfo.h - SuperH private data -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file declares the SuperH specific subclass of MachineFunctionInfo.
+///
+//===----------------------------------------------------------------------===//
+
+#include "SuperHMachineFunctionInfo.h"
+#include "SuperHConstantPoolValue.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include <type_traits>
+
+using namespace llvm;
+
+void SuperHMachineFunctionInfo::anchor() {}
+
+MachineFunctionInfo *SuperHMachineFunctionInfo::clone(
+    BumpPtrAllocator &Allocator, MachineFunction &DestMF,
+    const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
+    const {
+  return DestMF.cloneInfo<SuperHMachineFunctionInfo>(*this);
+}
+
+SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
+        GlobalAddressSDNode *N, 
+        SelectionDAG &DAG, 
+        SHCP::SHCPModifier Modifier) {
+
+  // Early exit for null node.
+  if (!N)
+    return nullptr;
+
+  // Run though the constant pool that is tied to the DAG and search for 
+  // the constant there.
+  MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+  for (auto &MC : MCP->getConstants()) {
+    if (MC.isMachineConstantPoolEntry()) {
+      if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+        if (CPV->getGV() == N->getGlobal())
+          return CPV;
+      }
+    }
+  }
+
+  // If not found, create a new one and add it.
+  MachineFunction &MF = DAG.getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+  unsigned LabelIndex = SFI->createConstIndex();
+  return SuperHConstantPoolConstant::Create(
+    N->getGlobal(), 
+    LabelIndex,
+    SHCP::SHCPKind::CPValue,
+    Modifier
+  );
+}
+
+SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
+        BlockAddressSDNode *N, 
+        SelectionDAG &DAG, 
+        SHCP::SHCPModifier Modifier) {
+
+  // Early exit for null node.
+  if (!N)
+    return nullptr;
+
+  // Run though the constant pool that is tied to the DAG and search for 
+  // the constant there.
+  MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+  for (auto &MC : MCP->getConstants()) {
+    if (MC.isMachineConstantPoolEntry()) {
+      if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+        if (CPV->getBlockAddress() == N->getBlockAddress())
+          return CPV;
+      }
+    }
+  }
+
+  // If not found, create a new one and add it.
+  MachineFunction &MF = DAG.getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+  unsigned LabelIndex = SFI->createConstIndex();
+  return SuperHConstantPoolConstant::Create(
+    N->getBlockAddress(), 
+    LabelIndex,
+    SHCP::SHCPKind::CPBlockAddress,
+    Modifier
+  );
+}
+
+SuperHConstantPoolSymbol *SuperHMachineFunctionInfo::tryGetConstant(
+        ExternalSymbolSDNode *N, 
+        SelectionDAG &DAG, 
+        SHCP::SHCPModifier Modifier) {
+
+  // Early exit for null node.
+  if (!N)
+    return nullptr;
+
+  // Run though the constant pool that is tied to the DAG and search for 
+  // the constant there.
+  MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+  for (auto &MC : MCP->getConstants()) {
+    if (MC.isMachineConstantPoolEntry()) {
+      if (auto *CPV = (SuperHConstantPoolSymbol*)MC.Val.MachineCPVal) {
+        if (CPV->getSymbol() == N->getSymbol())
+          return CPV;
+      }
+    }
+  }
+  
+  // If not found, create a new one and add it.
+  MachineFunction &MF = DAG.getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+  unsigned LabelIndex = SFI->createConstIndex();
+  return SuperHConstantPoolSymbol::Create(
+    *DAG.getContext(), 
+    N->getSymbol(), 
+    LabelIndex
+  );
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
new file mode 100644
index 0000000000000..33264e71670a0
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -0,0 +1,68 @@
+//===-- SuperHMachineFunctionInfo.h - SuperH private data -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file declares the SuperH specific subclass of MachineFunctionInfo.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SUPERH_SUPERHMACHINEFUNCTION_H
+#define LLVM_LIB_TARGET_SUPERH_SUPERHMACHINEFUNCTION_H
+
+#include "SuperHConstantPoolValue.h"
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/CodeGenTypes/MachineValueType.h"
+
+namespace llvm {
+
+class SuperHMachineFunctionInfo : public MachineFunctionInfo {
+
+  /// CPIndexCount - How many constant pool indices are allocated. 
+  unsigned CPIndexCount = 0;
+
+public:
+  explicit SuperHMachineFunctionInfo(const Function &F,
+                                     const TargetSubtargetInfo *STI) {}
+
+  MachineFunctionInfo *
+  clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
+        const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
+      const override;
+
+  // getConstIndexCount - Gets the amount of PIC Labels that have been
+  // created thus far.
+  unsigned getConstIndexCount() const { return CPIndexCount; }
+
+  // createConstIndex - Creates a new PIC Label UId.
+  unsigned createConstIndex() { return CPIndexCount++; }
+
+  // tryGetConstant - SuperH's compressed instruction set means that 
+  // immediates and displacements can not be larger than 8 bits. 
+  // As such we need to store said immediates and displacements within 
+  // constants that are within range of the program counter.
+  //
+  // As such this function is a helper that:
+  //  1. Allocates a constant pool slot for a given node
+  //  2. Inserts the target into said slot.
+  //  3. Returns the allocated slot, ready to be loaded via
+  //     a PC-relative load.
+  SuperHConstantPoolConstant *tryGetConstant(GlobalAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant *tryGetConstant(BlockAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolSymbol *tryGetConstant(ExternalSymbolSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+
+private:
+	virtual void anchor();
+};
+
+
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index f6053dbb48798..6c40c0f25fdd0 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -69,6 +69,9 @@ BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   // R0 is always reserved as some instructions can only write to it.
   Reserved.set(SH::R0);
 
+  // Reserve GOT pointer
+  Reserved.set(SH::R12);
+  
   // Also reserve the stack frame and stack pointer.
   Reserved.set(SH::R14);
   Reserved.set(SH::R15);
@@ -94,11 +97,10 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   if (MI.getOpcode() == SH::SHFrmIdx) {
 
     // TODO: Lower frames that can't be expressed in 4 bits.
-
     Register DstReg = MI.getOperand(0).getReg();
     MachineInstr *New = BuildMI(MBB, MI, dl, TII.get(SH::MOVLD4RmiRn), DstReg)
                         .addReg(SH::R14)
-                        .addImm(Offset / 4);
+                        .addImm(Offset);
 
     MI.eraseFromParent();
     return false;
@@ -116,4 +118,8 @@ Register SuperHRegisterInfo::getFrameRegister() const {
 
 Register SuperHRegisterInfo::getStackRegister() const {
   return SH::R15;
+}
+
+Register SuperHRegisterInfo::getGOTRegister() const {
+  return SH::R12;
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index c40cffab52e7a..0a69b4b9a8c2c 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -43,6 +43,7 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
   // Helpers
   Register getFrameRegister() const;
   Register getStackRegister() const;
+  Register getGOTRegister() const;
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
index 1cff7f9f647b4..4967df1a71c97 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SuperHSubtarget.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -24,12 +25,11 @@ using namespace llvm;
 #define GET_SUBTARGETINFO_CTOR
 #include "SuperHGenSubtargetInfo.inc"
 
-SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
-                               const StringRef &FS, const TargetMachine &TM)
-    : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, TuneCPU, FS),
+SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU, 
+                                 const StringRef &FS,  const TargetMachine &TM)
+    : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, TuneCPU, FS), TM(TM),
       InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)), 
-      TLInfo(TM, *this), FrameLowering(*this) {
-  // TSInfo = std::make_unique<SuperHSelectionDAGInfo>();
+      TLInfo(TM, *this), TSInfo(), FrameLowering(*this) {
 }
 
 SuperHSubtarget::~SuperHSubtarget() = default;
@@ -46,4 +46,110 @@ SuperHSubtarget &SuperHSubtarget::initializeSubtargetDependencies(
   // Parse features string.
   ParseSubtargetFeatures(CPUName, TuneCPU, FS);
   return *this;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                             Classification Functions
+//===----------------------------------------------------------------------===//
+
+SHRefClass SuperHSubtarget::classifyBlockAddressReference() const {
+  switch (TM.getCodeModel()) {
+  default:
+    llvm_unreachable("Unsupported code model");
+  case CodeModel::Small:
+  case CodeModel::Kernel: {
+    return SHII::MO_PCREL;
+  }
+  case CodeModel::Medium:
+  case CodeModel::Large: {
+    return isPositionIndependent() ? 
+           SHII::MO_PCREL : 
+           SHII::MO_DIR;
+  }
+  }
+}
+
+SHRefClass SuperHSubtarget::classifyLocalReference(const GlobalValue *GV) const {
+  switch (TM.getCodeModel()) {
+  default:
+    llvm_unreachable("Unsupported code model");
+  case CodeModel::Small:
+  case CodeModel::Kernel: {
+    return isPositionIndependent() ? 
+           SHII::MO_PCREL :
+           SHII::MO_DIR;
+  }
+  case CodeModel::Medium: {
+    return isPositionIndependent() ? 
+           SHII::MO_GOTOFF : 
+           SHII::MO_DIR;
+  }
+  case CodeModel::Large: {
+    return isPositionIndependent() ? 
+           SHII::MO_GOTOFF : 
+           SHII::MO_DIR;
+  }
+  }
+}
+
+SHRefClass SuperHSubtarget::classifyExternalReference(const Module &M) const {
+  if (TM.shouldAssumeDSOLocal(nullptr))
+    return classifyLocalReference(nullptr);
+
+  return isPositionIndependent() ? 
+         SHII::MO_GOTPC : 
+         SHII::MO_GOT;
+}
+
+SHRefClass SuperHSubtarget::classifyGlobalReference(const GlobalValue *GV) const {
+  return classifyGlobalReference(GV, *GV->getParent());
+}
+
+SHRefClass SuperHSubtarget::classifyGlobalReference(const GlobalValue *GV,
+                                   const Module &M) const {
+  if (TM.shouldAssumeDSOLocal(GV))
+    return classifyLocalReference(GV);
+
+  switch (TM.getCodeModel()) {
+  default:
+    llvm_unreachable("Unsupported code model");
+  case CodeModel::Small:
+  case CodeModel::Kernel:
+  case CodeModel::Medium: {
+    return isPositionIndependent() ? 
+           SHII::MO_GOTPC : 
+           SHII::MO_DIR;
+  }
+  case CodeModel::Large: {
+    return isPositionIndependent() ? 
+           SHII::MO_GOTOFF : 
+           SHII::MO_DIR;
+  }
+  }
+}
+
+SHRefClass SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
+                                           const Module &M) const {
+  if (TM.shouldAssumeDSOLocal(GV))
+    return SHII::MO_NO_FLAG;
+
+
+  // If the function is marked as non-lazy, generate an indirect call
+  // which loads from the GOT directly. This avoids run-time overhead
+  // at the cost of eager binding.
+  auto *F = dyn_cast_or_null<Function>(GV);
+  if (F && F->hasFnAttribute(Attribute::NonLazyBind)) {
+    return SHII::MO_GOTPC;
+  }
+
+  return isPositionIndependent() ? 
+         SHII::MO_PLT : 
+         SHII::MO_DIR;
+}
+
+SHRefClass SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
+  return classifyGlobalFunctionReference(GV, *GV->getParent());
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.h b/llvm/lib/Target/SuperH/SuperHSubtarget.h
index 7a2149e384b51..d3e767935ada7 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.h
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.h
@@ -18,9 +18,11 @@
 #include "SuperHISelLowering.h"
 #include "SuperHInstrInfo.h"
 #include "SuperHSelectionDAGInfo.h"
+#include "SuperHTargetMachine.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetMachine.h"
 #include "llvm/TargetParser/Triple.h"
 
 #define GET_SUBTARGETINFO_HEADER
@@ -29,6 +31,8 @@
 namespace llvm {
 class StringRef;
 
+typedef unsigned char SHRefClass;
+
 class SuperHSubtarget : public SuperHGenSubtargetInfo {
   enum SuperHArchEnum { 
     SHDefault,
@@ -40,6 +44,7 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
   
   SuperHArchEnum SHArchVersion;
 
+  const TargetMachine &TM;
   SuperHInstrInfo InstrInfo;
   SuperHTargetLowering TLInfo;
   SuperHSelectionDAGInfo TSInfo;
@@ -50,24 +55,42 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
 #include "SuperHGenSubtargetInfo.inc"
 
 public:
-  SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
-                 const StringRef &FS, const TargetMachine &TM);
+  SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU, 
+                  const StringRef &FS,  const TargetMachine &TM);
 
   ~SuperHSubtarget() override;
 
+  const Triple &getTargetTriple() const { return TM.getTargetTriple(); }
   const SuperHInstrInfo *getInstrInfo() const override { return &InstrInfo; }
-  const TargetFrameLowering *getFrameLowering() const override {
-    return &FrameLowering;
-  }
-  const SuperHRegisterInfo *getRegisterInfo() const override {
-    return &InstrInfo.getRegisterInfo();
-  }
-  const SuperHSelectionDAGInfo *getSelectionDAGInfo() const override {
-    return &TSInfo;
-  }
-  const SuperHTargetLowering *getTargetLowering() const override {
-    return &TLInfo;
-  }
+  const TargetFrameLowering *getFrameLowering() const override { return &FrameLowering; }
+  const SuperHRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); }
+  const SuperHSelectionDAGInfo *getSelectionDAGInfo() const override { return &TSInfo; }
+  const SuperHTargetLowering *getTargetLowering() const override { return &TLInfo; }
+
+  bool isTargetELF() const { return getTargetTriple().isOSBinFormatELF(); }
+  bool isPositionIndependent() const { return TM.isPositionIndependent(); }
+
+  // Classification functions
+  SHRefClass classifyLocalReference(const GlobalValue *GV) const;
+
+  /// Classify a global variable reference for the current subtarget according
+  /// to how we should reference it in a non-pcrel context.
+  SHRefClass classifyGlobalReference(const GlobalValue *GV,
+                                     const Module &M) const;
+  SHRefClass classifyGlobalReference(const GlobalValue *GV) const;
+
+  /// Classify a external variable reference for the current subtarget according
+  /// to how we should reference it in a non-pcrel context.
+  SHRefClass classifyExternalReference(const Module &M) const;
+
+  /// Classify a global function reference for the current subtarget.
+  SHRefClass classifyGlobalFunctionReference(const GlobalValue *GV,
+                                             const Module &M) const;
+  SHRefClass classifyGlobalFunctionReference(const GlobalValue *GV) const override;
+
+  /// Classify a blockaddress reference for the current subtarget according to
+  /// how we should reference it in a non-pcrel context.
+  SHRefClass classifyBlockAddressReference() const;
 
 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
   bool GETTER() const { return ATTRIBUTE; }
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 09befc32c7ead..0d8e004954cac 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -13,11 +13,14 @@
 #include "SuperHTargetMachine.h"
 #include "SuperH.h"
 #include "SuperHSubtarget.h"
+#include "SuperHMachineFunctionInfo.h"
 #include "TargetInfo/SuperHTargetInfo.h"
+#include "llvm/CodeGen/BranchFoldingPass.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 #include "llvm/CodeGen/TargetPassConfig.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/PassRegistry.h"
 #include "llvm/Support/Compiler.h"
 #include <optional>
 
@@ -26,6 +29,12 @@ using namespace llvm;
 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSuperHTarget() {
   RegisterTargetMachine<SuperHTargetMachine> SH(getTheSuperHTarget());
   RegisterTargetMachine<SuperHTargetMachine> SHLE(getTheSuperHLETarget());
+
+  PassRegistry &Registry = *PassRegistry::getPassRegistry();
+  initializeSuperHAsmPrinterPass(Registry);
+  initializeSuperHFillDelaySlotsPass(Registry);
+  initializeSuperHConstantIslandsPass(Registry);
+  initializeSuperHDAGToDAGISelLegacyPass(Registry);
 }
 
 //
@@ -40,6 +49,8 @@ class SuperHPassConfig : public TargetPassConfig {
 
   bool addInstSelector() override;
   void addPreSched2() override;
+  void addPreEmitPass() override;
+  void addPreEmitPass2() override;
   SuperHTargetMachine &getSuperHTargetMachine() const {
     return getTM<SuperHTargetMachine>();
   }
@@ -51,9 +62,22 @@ bool SuperHPassConfig::addInstSelector() {
 }
 
 void SuperHPassConfig::addPreSched2() {
+}
+
+void SuperHPassConfig::addPreEmitPass() {
+  addPass(&BranchFolderPassID);
+  addPass(&IfConverterID);
   addPass(createSuperHFillDelaySlotsPass());
 }
 
+void SuperHPassConfig::addPreEmitPass2() {
+
+  // Inserts Constant Islands. Block sizes cannot be increased after this point,
+  // as this may push the branch ranges and load offsets of accessing constant
+  // pools out of range.
+  addPass(createSuperHConstantIslandPass());
+}
+
 } // namespace
 
 
@@ -100,4 +124,11 @@ SuperHTargetMachine::getSubtargetImpl(const Function &F) const {
     ST = std::make_unique<SuperHSubtarget>(CPU, TuneCPU, FS, *this);
   }
   return ST.get();
+}
+
+MachineFunctionInfo *
+SuperHTargetMachine::createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
+                          const TargetSubtargetInfo *STI) const {
+  return SuperHMachineFunctionInfo::create<SuperHMachineFunctionInfo>(Allocator, F,
+                                                                  STI);
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.h b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
index 3b2872ed50ffd..63b722fff7a57 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.h
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
@@ -33,6 +33,10 @@ class SuperHTargetMachine : public CodeGenTargetMachineImpl {
                      bool JIT);
   ~SuperHTargetMachine() override;
 
+  MachineFunctionInfo *
+  createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
+                            const TargetSubtargetInfo *STI) const override;
+
   const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override;
   TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
   TargetLoweringObjectFile *getObjFileLowering() const override {

>From 5e1edd01b2d394291c8396319ef5c0566553c142 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sat, 22 Aug 2026 00:49:48 +0200
Subject: [PATCH 22/67] Handle i1, i8 and i16 sign/zero extend loads and O2+
 branches

---
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp |   3 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 151 ++++++++++++++++--
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |   1 +
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  53 ++++++
 .../lib/Target/SuperH/SuperHTargetMachine.cpp |   2 -
 5 files changed, 191 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 59b297b48f886..252bb5952524d 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -69,8 +69,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   for (MVT VT : MVT::integer_valuetypes()) {
     for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
       setLoadExtAction(N, VT, MVT::i1, Promote);
-      setLoadExtAction(N, VT, MVT::i8, Promote);
-      setLoadExtAction(N, VT, MVT::i16, Promote);
+      setLoadExtAction(N, VT, MVT::i64, Expand);
     }
   }
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 07523d475b3c5..e27b09e12fd4f 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -72,16 +72,25 @@ void SuperHInstrInfo::insertNoop(MachineBasicBlock &MBB,
 ISD::CondCode SuperHInstrInfo::getCondFromBranchOp(unsigned Op) const {
   switch (Op) {
   default:
-    return ISD::SETFALSE;
-  case SH::BRA:
+    return ISD::SETCC_INVALID;
   case SH::NOP:
-    return ISD::SETTRUE;
   case SH::BT:
   case SH::BTS:
-    return ISD::SETEQ;
+    return ISD::SETTRUE;
   case SH::BF:
   case SH::BFS:
-    return ISD::SETNE;
+    return ISD::SETFALSE;
+  }
+}
+
+ISD::CondCode SuperHInstrInfo::getOppositeCondCode(ISD::CondCode Op) const {
+  switch (Op) {
+  default:
+    return ISD::SETCC_INVALID;
+  case ISD::SETTRUE:
+    return ISD::SETFALSE;
+  case ISD::SETFALSE:
+    return ISD::SETTRUE;
   }
 }
 
@@ -89,13 +98,9 @@ const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
   switch (CC) {
   default:
     llvm_unreachable("Unknown condition code!");
-  case ISD::SETEQ:
-  case ISD::SETGE:
-  case ISD::SETGT:
+  case ISD::SETTRUE:
     return get(SH::BT);
-  case ISD::SETNE:
-  case ISD::SETLE:
-  case ISD::SETLT:
+  case ISD::SETFALSE:
     return get(SH::BF);
   }
 }
@@ -151,14 +156,18 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
       continue;
     }
 
-    LLVM_DEBUG(dbgs() << "analyzeBranch " << getName(I->getOpcode()) << "\n");
-
     // Working from the bottom, when we see a non-terminator
     // instruction, we're done.
     if (!isUnpredicatedTerminator(*I)) {
       break;
     }
 
+    // A terminator that isn't a branch can't easily be handled
+    // by this analysis.
+    if (!I->getDesc().isBranch()) {
+      return true;
+    }
+
     // Handle unconditional branches.
     if (I->getOpcode() == SH::BRA) {
       UnCondBrIter = I;
@@ -186,6 +195,56 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
       TBB = I->getOperand(0).getMBB();
       continue;
     }
+
+    // Handle conditional branches.
+    ISD::CondCode BranchCode = getCondFromBranchOp(I->getOpcode());
+    if (BranchCode == ISD::SETFALSE) {
+      return true; // Can't handle indirect branch.
+    }
+
+    // Working from the bottom, handle the first conditional branch.
+    if (Cond.empty()) {
+      MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
+      if (AllowModify && UnCondBrIter != MBB.end() &&
+          MBB.isLayoutSuccessor(TargetBB)) {
+
+        BranchCode = getOppositeCondCode(BranchCode);
+        unsigned JNCC = getBrCond(BranchCode).getOpcode();
+        MachineBasicBlock::iterator OldInst = I;
+
+        BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
+            .addMBB(UnCondBrIter->getOperand(0).getMBB());
+        BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SH::BRA))
+            .addMBB(TargetBB);
+
+        OldInst->eraseFromParent();
+        UnCondBrIter->eraseFromParent();
+
+        // Restart the analysis.
+        UnCondBrIter = MBB.end();
+        I = MBB.end();
+        continue;
+      }
+
+      // Handle subsequent conditional branches. Only handle the case where all
+      // conditional branches branch to the same destination.
+      assert(Cond.size() == 1);
+      assert(TBB);
+
+      // Only handle the case where all conditional branches branch to
+      // the same destination.
+      if (TBB != I->getOperand(0).getMBB()) {
+        return true;
+      }
+
+      ISD::CondCode OldBranchCode = (ISD::CondCode)Cond[0].getImm();
+      // If the conditions are the same, we can leave them alone.
+      if (OldBranchCode == BranchCode) {
+        continue;
+      }
+
+      return true;
+    }
   }
 
   return false;
@@ -195,17 +254,79 @@ unsigned SuperHInstrInfo::insertBranch(MachineBasicBlock &MBB, MachineBasicBlock
                       MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
                       const DebugLoc &DL,
                       int *BytesAdded) const {
-  return 0;
+  if (BytesAdded)
+    *BytesAdded = 0;
+
+  // Shouldn't be a fall through.
+  assert(TBB && "insertBranch must not be told to insert a fallthrough");
+  assert((Cond.size() == 1 || Cond.size() == 0) &&
+         "SH branch conditions have one component!");
+
+  if (Cond.empty()) {
+    assert(!FBB && "Unconditional branch with multiple successors!");
+    auto &MI = *BuildMI(&MBB, DL, get(SH::BRA)).addMBB(TBB);
+    if (BytesAdded)
+      *BytesAdded += getInstSizeInBytes(MI);
+    return 1;
+  }
+
+  // Conditional branch.
+  unsigned Count = 0;
+  ISD::CondCode CC = (ISD::CondCode)Cond[0].getImm();
+  auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
+
+  if (BytesAdded)
+    *BytesAdded += getInstSizeInBytes(CondMI);
+  ++Count;
+
+  if (FBB) {
+    // Two-way Conditional branch. Insert the second branch.
+    auto &MI = *BuildMI(&MBB, DL, get(SH::BRA)).addMBB(FBB);
+    if (BytesAdded)
+      *BytesAdded += getInstSizeInBytes(MI);
+    ++Count;
+  }
+
+  return Count;
 }
 
 unsigned SuperHInstrInfo::removeBranch(MachineBasicBlock &MBB,
                       int *BytesRemoved) const {
-  return 0;
+  if (BytesRemoved)
+    *BytesRemoved = 0;
+
+  MachineBasicBlock::iterator I = MBB.end();
+  unsigned Count = 0;
+
+  while (I != MBB.begin()) {
+    --I;
+    if (I->isDebugInstr()) {
+      continue;
+    }
+
+    if (I->getOpcode() != SH::BRA &&
+        getCondFromBranchOp(I->getOpcode()) == ISD::SETCC_INVALID) {
+      break;
+    }
+
+    // Remove the branch.
+    if (BytesRemoved)
+      *BytesRemoved += getInstSizeInBytes(*I);
+    I->eraseFromParent();
+    I = MBB.end();
+    ++Count;
+  }
+
+  return Count;
 }
 
 bool
 SuperHInstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+  assert(Cond.size() == 1 && "Invalid SH branch condition!");
 
+  ISD::CondCode CC = static_cast<ISD::CondCode>(Cond[0].getImm());
+  Cond[0].setImm(getOppositeCondCode(CC));
+  return false;
 }
 
 MachineBasicBlock *SuperHInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 3b309249c8b22..da25ff9390727 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -42,6 +42,7 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   /// to be chained together.
   bool canFillDelaySlot(unsigned Opcode) const;
   ISD::CondCode getCondFromBranchOp(unsigned Op) const;
+  ISD::CondCode getOppositeCondCode(ISD::CondCode CC) const;
   const MCInstrDesc &getBrCond(ISD::CondCode CC) const;
 
   // Instruction Info
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index deff63e16f00b..6826583a17c80 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -636,6 +636,38 @@ let hasSideEffects = 0, isCommutable = 1 in {
 
 
 
+//===--------------------------------------------------------------------------===//
+// Sign/Zero Extend
+//===--------------------------------------------------------------------------===//
+  
+// exts.b Rm, Rn
+def EXTSBRmRn       : InstRmRn<0b0110000000001110, 
+                              (outs GPR:$Rn), (ins GPR:$Rm),
+                              "exts.b $Rm,$Rn",
+                              [(set i32:$Rn, (sext i8:$Rm))]>;
+
+// exts.w Rm, Rn
+def EXTSWRmRn       : InstRmRn<0b0110000000001111, 
+                              (outs GPR:$Rn), (ins GPR:$Rm),
+                              "exts.w $Rm,$Rn",
+                             [(set i32:$Rn, (sext i16:$Rm))]>;
+
+// extu.b Rm, Rn
+def EXTUBRmRn       : InstRmRn<0b0110000000001100, 
+                             (outs GPR:$Rn), (ins GPR:$Rm),
+                             "extu.b $Rm,$Rn",
+                             [(set i32:$Rn, (zext i8:$Rm))]>;
+
+// extu.w Rm, Rn
+def EXTUWRmRn       : InstRmRn<0b0110000000001101, 
+                              (outs GPR:$Rn), (ins GPR:$Rm),
+                             "extu.w $Rm,$Rn",
+                              [(set i32:$Rn, (zext i16:$Rm))]>;
+
+
+
+
+
 //===--------------------------------------------------------------------------===//
 // Comparison
 //===--------------------------------------------------------------------------===//
@@ -1193,6 +1225,27 @@ include "SuperHInstrDSP.td"
 
 
 
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                            Non-Instruction Patterns
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+//===--------------------------------------------------------------------------===//
+// Zero-Extend Load
+//===--------------------------------------------------------------------------===//
+
+def : Pat<(i32 (zextloadi1 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
+def : Pat<(i32 (zextloadi8 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
+def : Pat<(i32 (zextloadi16 i32:$src)), (EXTUWRmRn (MOVWRmiRn i32:$src))>;
+def : Pat<(i32 (extloadi1 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+def : Pat<(i32 (extloadi8 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+def : Pat<(i32 (extloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
+
+
+
+
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 //                              Pseudo instructions
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 0d8e004954cac..86a4a4c41bd85 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -65,8 +65,6 @@ void SuperHPassConfig::addPreSched2() {
 }
 
 void SuperHPassConfig::addPreEmitPass() {
-  addPass(&BranchFolderPassID);
-  addPass(&IfConverterID);
   addPass(createSuperHFillDelaySlotsPass());
 }
 

>From 6f244527716d79c49a9c5c5e2158371e6ba1a5ac Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 31 Aug 2026 05:01:43 +0200
Subject: [PATCH 23/67] Fix little endian target name to match GCC

---
 clang/lib/Basic/Targets.cpp                   |  2 +-
 llvm/include/llvm/TargetParser/Triple.h       |  4 ++--
 .../SuperH/TargetInfo/SuperHTargetInfo.cpp    |  4 ++--
 llvm/lib/TargetParser/TargetDataLayout.cpp    |  4 ++--
 llvm/lib/TargetParser/Triple.cpp              | 22 +++++++++----------
 5 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index d65774fc08c3b..a48e9fe0671c6 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -554,7 +554,7 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
     }
     
   case llvm::Triple::sh:
-  case llvm::Triple::sh_le:
+  case llvm::Triple::shl:
     switch (os) {
     default:
       return std::make_unique<SuperHTargetInfo>(Triple, Opts);
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 235b691789720..475137cb38579 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -81,7 +81,7 @@ class Triple {
     riscv32be,   // RISC-V (32-bit, big endian): riscv32be
     riscv64be,   // RISC-V (64-bit, big endian): riscv64be
     sh,          // SuperH (big endian): sh
-    sh_le,       // SuperH (little endian): sh_le
+    shl,         // SuperH (little endian): shl
     sparc,       // Sparc: sparc
     sparcv9,     // Sparcv9: Sparcv9
     sparcel,     // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
@@ -1194,7 +1194,7 @@ class Triple {
 
   /// Tests whether the target is SuperH.
   bool isSuperH() const { 
-    return getArch() == Triple::sh || getArch() == Triple::sh_le;
+    return getArch() == Triple::sh || getArch() == Triple::shl;
   }
 
   /// Tests whether the target is SystemZ.
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
index 83c5970fc6783..f206de2dabc90 100644
--- a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
@@ -26,6 +26,6 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY
 void LLVMInitializeSuperHTargetInfo() {
   RegisterTarget<Triple::sh, /*HasJIT=*/false> X(getTheSuperHTarget(),
                                                     "sh", "SuperH (big endian)", "SuperH");
-  RegisterTarget<Triple::sh_le, /*HasJIT=*/false> Y(getTheSuperHLETarget(),
-                                                    "sh_le", "SuperH (little endian)", "SuperH");
+  RegisterTarget<Triple::shl, /*HasJIT=*/false> Y(getTheSuperHLETarget(),
+                                                    "shl", "SuperH (little endian)", "SuperH");
 }
diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp
index ca8ebf1cef240..2321190fa50be 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -567,7 +567,7 @@ static std::string computeVEDataLayout(const Triple &T) {
 static std::string computeSuperHDataLayout(const Triple &T) {
 
   // Mixed-endian
-  std::string Ret = T.getArch() == Triple::sh_le ? "e" : "E";
+  std::string Ret = T.getArch() == Triple::shl ? "e" : "E";
 
   // ELF name manging
   Ret += "-m:e";
@@ -656,7 +656,7 @@ std::string Triple::computeDataLayout(StringRef ABIName) const {
   case Triple::systemz:
     return computeSystemZDataLayout(*this);
   case Triple::sh:
-  case Triple::sh_le:
+  case Triple::shl:
     return computeSuperHDataLayout(*this);
   case Triple::tce:
     return "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:32-"
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 00a9d53596ec1..89f28ac866110 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -121,8 +121,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
     return "riscv64be";
   case sh:
     return "sh";
-  case sh_le:
-    return "sh_le";
+  case shl:
+    return "shl";
   case shave:
     return "shave";
   case sparc:
@@ -492,7 +492,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
       .Case("riscv64be", riscv64be)
       .Case("hexagon", hexagon)
       .Case("sh", sh)
-      .Case("sh_le", sh_le)
+      .Case("shl", shl)
       .Case("sparc", sparc)
       .Case("sparcel", sparcel)
       .Case("sparcv9", sparcv9)
@@ -649,7 +649,7 @@ Triple::ArchType Triple::parseArch(StringRef ArchName) {
           .Case("hexagon", Triple::hexagon)
           .Cases({"s390x", "systemz"}, Triple::systemz)
           .Case("sh", Triple::sh)
-          .Case("sh_le", Triple::sh_le)
+          .Case("shl", Triple::shl)
           .Case("sparc", Triple::sparc)
           .Case("sparcel", Triple::sparcel)
           .Cases({"sparcv9", "sparc64"}, Triple::sparcv9)
@@ -1004,7 +1004,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
   case Triple::riscv32be:
   case Triple::riscv64be:
   case Triple::sh:
-  case Triple::sh_le:
+  case Triple::shl:
   case Triple::shave:
   case Triple::sparc:
   case Triple::sparcel:
@@ -1772,7 +1772,7 @@ unsigned Triple::getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
   case llvm::Triple::riscv32:
   case llvm::Triple::riscv32be:
   case llvm::Triple::sh:
-  case llvm::Triple::sh_le:
+  case llvm::Triple::shl:
   case llvm::Triple::shave:
   case llvm::Triple::sparc:
   case llvm::Triple::sparcel:
@@ -1885,7 +1885,7 @@ Triple Triple::get32BitArchVariant() const {
   case Triple::riscv32:
   case Triple::riscv32be:
   case Triple::sh:
-  case Triple::sh_le:
+  case Triple::shl:
   case Triple::shave:
   case Triple::sparc:
   case Triple::sparcel:
@@ -1979,7 +1979,7 @@ Triple Triple::get64BitArchVariant() const {
   case Triple::msp430:
   case Triple::r600:
   case Triple::sh:
-  case Triple::sh_le:
+  case Triple::shl:
   case Triple::shave:
   case Triple::sparcel:
   case Triple::tce:
@@ -2160,7 +2160,7 @@ Triple Triple::getBigEndianArchVariant() const {
   case Triple::sparcel:
     T.setArch(Triple::sparc);
     break;
-  case Triple::sh_le:
+  case Triple::shl:
     T.setArch(Triple::sh);
     break;
   case Triple::tcele:
@@ -2219,7 +2219,7 @@ Triple Triple::getLittleEndianArchVariant() const {
     T.setArch(Triple::sparcel);
     break;
   case Triple::sh:
-    T.setArch(Triple::sh_le);
+    T.setArch(Triple::shl);
     break;
   case Triple::tce:
     T.setArch(Triple::tcele);
@@ -2261,7 +2261,7 @@ bool Triple::isLittleEndian() const {
   case Triple::riscv32:
   case Triple::riscv64:
   case Triple::shave:
-  case Triple::sh_le:
+  case Triple::shl:
   case Triple::sparcel:
   case Triple::spir64:
   case Triple::spir:

>From e6f39fe35bfba11680162d9b3a21f7a93f5248cc Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 1 Sep 2026 09:11:00 +0200
Subject: [PATCH 24/67] Refactor ASM parser

---
 .../SuperH/AsmParser/SuperHAsmParser.cpp      | 566 +++++++++++++-----
 .../SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp   |   3 +-
 llvm/lib/Target/SuperH/SuperH.td              |   5 +-
 3 files changed, 409 insertions(+), 165 deletions(-)

diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 5fa685f814828..6e45a5388068e 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -36,6 +36,7 @@
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/LogicalResult.h"
 #include "llvm/Support/SMLoc.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/DebugLog.h"
@@ -44,6 +45,8 @@
 #include <sstream>
 #include <system_error>
 
+#define DEBUG_TYPE "sh-asmparser"
+
 using namespace llvm;
 
 // The generated AsmMatcher SparcGenAsmMatcher uses "SuperH" as the target
@@ -72,9 +75,6 @@ class SuperHAsmParser : public MCTargetAsmParser {
 #define GET_ASSEMBLER_HEADER
 #include "SuperHGenAsmMatcher.inc"
 
-  bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
-  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
-  MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
   bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override;
   ParseStatus parseDirective(AsmToken DirectiveID) override;
   bool parseGNUAttribute(SMLoc L);
@@ -83,9 +83,26 @@ class SuperHAsmParser : public MCTargetAsmParser {
                                        uint64_t &ErrorInfo,
                                        bool MatchingInlineAsm) override;
 
+  // Register Parsing
+  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
+
+  // Parser helpers.
+  MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
+  ParseStatus tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc);
+  ParseStatus tryParseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc);
+  ParseStatus tryParseRegRelative(MCRegister &BaseReg, MCRegister &OffReg, const MCExpr *&Offset, SMLoc &StartLoc, SMLoc &EndLoc);
+  ParseStatus tryParseRegIndirect(MCRegister &Reg, bool &IsInc, bool &IsDec, SMLoc &StartLoc, SMLoc &EndLoc);
+
+  // Parser entry points
   ParseStatus parseOperand(OperandVector &Operands);
-  ParseStatus parseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc);
-  ParseStatus parseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc);
+  ParseStatus parseRegister(OperandVector &Operands);
+  ParseStatus parseRegisterIndirect(OperandVector &Operands);
+  ParseStatus parseRegisterIndirectInc(OperandVector &Operands);
+  ParseStatus parseRegisterIndirectDec(OperandVector &Operands);
+  ParseStatus parsePCRel(OperandVector &Operands);
+  ParseStatus parseImm(OperandVector &Operands);
+  ParseStatus parseDisp(OperandVector &Operands);
 
 public:
   SuperHAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII) 
@@ -108,7 +125,9 @@ class SuperHOperand : public MCParsedAsmOperand {
     rk_FR32,
     rk_FR64,
     rk_VEC128,
-    rk_XMTRX
+    rk_XMTRX,
+    rk_SYS,
+    rk_CTRL,
   };
 
 private:
@@ -144,10 +163,6 @@ class SuperHOperand : public MCParsedAsmOperand {
     const MCExpr *Val;
   };
 
-  struct DispOp {
-    const MCExpr *Val;
-  };
-
   struct ExprOp {
     const MCExpr *Val;
   };
@@ -162,7 +177,6 @@ class SuperHOperand : public MCParsedAsmOperand {
     struct Token Tok;
     struct RegOp Reg;
     struct ImmOp Imm;
-    struct DispOp Disp;
     struct MemOp Mem;
     struct ExprOp Expr;
     unsigned ASI;
@@ -180,6 +194,7 @@ class SuperHOperand : public MCParsedAsmOperand {
   bool isMem() const override { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec | k_IndirectIndex)) != 0; }
   bool isIndirectReg() const { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec)) != 0; }
   bool isAnyReg() const { return isReg() || isIndirectReg(); }
+  bool isPCRel() const { return Kind == k_Displacement && Mem.Base == SH::PC; }
 
   SMLoc getStartLoc() const override { return StartLoc; }
   SMLoc getEndLoc() const override { return EndLoc; }
@@ -206,6 +221,17 @@ class SuperHOperand : public MCParsedAsmOperand {
     this->addExpr(Inst, Expr);
   }
 
+  void addPCRelOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    const MCExpr *Expr = getDisp();
+    this->addExpr(Inst, Expr);
+  }
+
+  void addIRegOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createReg(getReg()));
+  }
+
   void addExpr(MCInst &Inst, const MCExpr *Expr) const{
     // Add as immediate when possible.  Null MCExpr = 0.
     if (!Expr)
@@ -233,7 +259,7 @@ class SuperHOperand : public MCParsedAsmOperand {
 
   const MCExpr *getDisp() const {
     assert((Kind & k_Displacement) && "Invalid access!");
-    return Disp.Val;
+    return Mem.Offset;
   }
 
   const MCExpr *getOffset() const {
@@ -268,17 +294,19 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateDisp(const MCExpr *Val, SMLoc S, SMLoc E) {
+  static std::unique_ptr<SuperHOperand> CreateDisp(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {
     auto Op = std::make_unique<SuperHOperand>(k_Displacement);
-    Op->Imm.Val = Val;
+    Op->Mem.Base = Reg;
+    Op->Mem.Offset = Val;
     Op->StartLoc = S;
     Op->EndLoc = E;
     return Op;
   }
 
   static std::unique_ptr<SuperHOperand> CreateSymRef(const MCExpr *Val, SMLoc S, SMLoc E) {
-    auto Op = std::make_unique<SuperHOperand>(k_Immediate | k_Displacement);
-    Op->Imm.Val = Val;
+    auto Op = std::make_unique<SuperHOperand>(k_Displacement);
+    Op->Mem.Base = SH::PC;
+    Op->Mem.Offset = Val;
     Op->StartLoc = S;
     Op->EndLoc = E;
     return Op;
@@ -332,10 +360,10 @@ class SuperHOperand : public MCParsedAsmOperand {
   static std::unique_ptr<SuperHOperand> CreateFromExpr(const MCExpr *Expr, 
                                                    SMLoc S, SMLoc E) {
     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
-      return CreateDisp(CE, S, E);
+      return CreateDisp(SH::PC, CE, S, E);
 
     if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
-      return CreateDisp(SRE, S, E);
+      return CreateSymRef(SRE, S, E);
     }
 
     return CreateExpr(Expr, S, E);
@@ -376,44 +404,42 @@ class SuperHOperand : public MCParsedAsmOperand {
 
 MCRegister SuperHAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegKind) {
   RegKind = SuperHOperand::rk_None;
-  if(!Tok.is(AsmToken::Identifier))
+  if(Tok.isNot(AsmToken::Identifier))
     return SH::NoRegister;
 
-  StringRef Name = Tok.getString();
-  MCRegister Reg = MatchRegisterName(Name.lower());
-  if (Reg) {
-
-    // XMTRX register.
-    if (Reg == SH::XMTRX) {
-      RegKind = SuperHOperand::rk_XMTRX;
-      return Reg;
-    }
-
+  std::string Name = Tok.getString().lower();
+  MCRegister Reg = MatchRegisterName(Name);
+  if (MRI.getRegClass(SH::GPRRegClassID).contains(Reg)) {
+    
     // General purpose register class.
-    if (MRI.getRegClass(SH::GPRRegClassID).contains(Reg)) {
-      RegKind = SuperHOperand::rk_GPR;
-      return Reg;
-    }
-
+    RegKind = SuperHOperand::rk_GPR;
+  } else if (Reg == SH::XMTRX) {
+    
+    // XMTRX register.
+    RegKind = SuperHOperand::rk_XMTRX;
+  } else if (MRI.getRegClass(SH::SYSRegClassID).contains(Reg)) {
+    
+    // System register class.
+    RegKind = SuperHOperand::rk_SYS;
+  } else if (MRI.getRegClass(SH::CTRLRegClassID).contains(Reg)) {
+    
+    // Control register class.
+    RegKind = SuperHOperand::rk_CTRL;
+  } else if (MRI.getRegClass(SH::FR32RegClassID).contains(Reg)) {
+    
     // 32-bit float registers.
-    if (MRI.getRegClass(SH::FR32RegClassID).contains(Reg)) {
-      RegKind = SuperHOperand::rk_FR32;
-      return Reg;
-    }
-
+    RegKind = SuperHOperand::rk_FR32;
+  } else if (MRI.getRegClass(SH::FR64RegClassID).contains(Reg)) {
+    
     // 64-bit float registers.
-    if (MRI.getRegClass(SH::FR64RegClassID).contains(Reg)) {
-      RegKind = SuperHOperand::rk_FR64;
-      return Reg;
-    }
-
+    RegKind = SuperHOperand::rk_FR64;
+  } else if (MRI.getRegClass(SH::VEC128RegClassID).contains(Reg)) {
+    
     // 128-bit vector registers.
-    if (MRI.getRegClass(SH::VEC128RegClassID).contains(Reg)) {
-      RegKind = SuperHOperand::rk_VEC128;
-      return Reg;
-    }
+    RegKind = SuperHOperand::rk_VEC128;
   }
-  return SH::NoRegister;
+
+  return Reg;
 }
 
 bool SuperHAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) {
@@ -430,7 +456,7 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
 
   // SuperH Registers are in the form of an identifier.
   Reg = SH::NoRegister;
-  if (getLexer().getKind() != AsmToken::Identifier)
+  if (getLexer().isNot(AsmToken::Identifier))
     return ParseStatus::NoMatch;
 
   // Match.
@@ -443,165 +469,392 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
   return ParseStatus::Success;
 }
 
-ParseStatus SuperHAsmParser::parseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
-  const AsmToken &Tok = Parser.getTok();
-  const MCExpr *Expr;
+
+
+
+//===----------------------------------------------------------------------===//
+//                            Parser Helpers
+//===----------------------------------------------------------------------===//
+
+// Try parsing a register by its name.
+ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc) {
+  const AsmToken Tok = Parser.getTok();
   StartLoc = Tok.getLoc();
   EndLoc = Tok.getEndLoc();
 
+  // SuperH Registers are in the form of an identifier.
+  Reg = SH::NoRegister;
+  if (getLexer().isNot(AsmToken::Identifier))
+    return ParseStatus::NoMatch;
+
+  // Match.
+  Reg = matchRegisterName(Tok, RegKind);
+  if (RegKind == SuperHOperand::rk_None)
+    return ParseStatus::NoMatch;
+
+  // Consume the register.
+  Parser.Lex();
+  return ParseStatus::Success;
+}
+
+// Parses register relative addressing modes.
+ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister &OffReg, 
+                                                 const MCExpr *&Offset, SMLoc &StartLoc, 
+                                                 SMLoc &EndLoc) {
+  const AsmToken Tok = getTok();
+  unsigned RegKind;
+
+  // NOTE:  SuperH Assemblers support subtituting the normal PC-relative form
+  //        with a symbol reference.
+  //
+  //        The following instruction sequences are equivalent:        
+  //          mova .ABC, r0  
+  //          mova @(.ABC,pc), r0
+  //          mova @(8,pc), r0      (Where 8 is an offset from PC that refers
+  //                                 to the same address as the identifier would)
+  if (getTok().is(AsmToken::Identifier)) {
+
+    // Registers are *not* identifiers.
+    if (matchRegisterName(getTok(), RegKind) != SH::NoRegister) {
+      return ParseStatus::NoMatch;
+    }
+
+    auto *Sym = getContext().getOrCreateSymbol(getTok().getIdentifier());
+    Offset = MCSymbolRefExpr::create(Sym, getContext());
+    BaseReg = SH::PC;
+    Parser.Lex();
+    return ParseStatus::Success;
+  }
+
+  // Parse "@(" sequence
+  if (getTok().isNot(AsmToken::At))
+    return ParseStatus::NoMatch;
+  Parser.Lex();
+
+  if (getTok().isNot(AsmToken::LParen)) {
+    getLexer().UnLex(Tok);
+    return ParseStatus::NoMatch;
+  }
+  Parser.Lex();
+
+  // Parse identifier
+  if (getTok().is(AsmToken::Identifier)) {
+
+    // Try parsing base-register as well as identifiers.
+    if (tryParseRegister(OffReg, RegKind, StartLoc, EndLoc).isNoMatch()) {
+
+      auto *Sym = getContext().getOrCreateSymbol(getTok().getIdentifier());
+      Offset = MCSymbolRefExpr::create(Sym, getContext());
+      Parser.Lex();
+    }
+  } else if (getTok().is(AsmToken::Integer)) {
+
+    // Try parsing numeric displacements.
+    if (Parser.parseExpression(Offset, EndLoc)) {
+      getLexer().UnLex(Tok);
+      return ParseStatus::NoMatch;
+    }
+  } else {
+    getLexer().UnLex(Tok);
+    return ParseStatus::NoMatch;
+  }
+
+  // Parse seperator
+  if (getTok().isNot(AsmToken::Comma)) {
+    getLexer().UnLex(Tok);
+    return ParseStatus::NoMatch;
+  }
+  Parser.Lex();
+
+  // Parse base register
+  if (tryParseRegister(BaseReg, RegKind, StartLoc, EndLoc).isNoMatch()) {
+    getLexer().UnLex(Tok);
+    return ParseStatus::NoMatch;
+  }
+
+  // Whoops! missing ending parenthesis.
+  if (getTok().isNot(AsmToken::RParen)) {
+    getLexer().UnLex(Tok);
+    return ParseStatus::NoMatch;
+  }
+
+  Parser.Lex();
+  return ParseStatus::Success;
+}
+
+// Parses register-indirect addressing in the following forms:
+// 
+//   @Rn  - Register Indirect
+//   @-Rn - Register Indirect with Pre-decrement
+//   @Rn+ - Register Indirect with Post-increment
+ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, bool &IsDec, 
+                                                 SMLoc &StartLoc, SMLoc &EndLoc) {
+  const AsmToken Tok = Parser.getTok();
+  SMLoc S = StartLoc;
+  SMLoc E = EndLoc;
+  unsigned RegKind;
+
+  if (getTok().isNot(AsmToken::At))
+    return ParseStatus::NoMatch;
+  Parser.Lex();
+
+  // Parse possible pre-decement
+  if (getTok().is(AsmToken::Minus)) {
+    IsDec = true;
+    Parser.Lex();
+  }
+
+  // Parse Register
+  if (tryParseRegister(Reg, RegKind, S, E).isNoMatch()) {
+    getLexer().UnLex(Tok);
+    return ParseStatus::NoMatch;
+  }
+
+  // Parse possible post-increment
+  if (Tok.is(AsmToken::Plus)) {
+    IsInc = true;
+    Parser.Lex();
+  }
+
+  // You can't do both increment and decrement.
+  // this is just a straight up syntax error.
+  if (IsInc && IsDec) {
+    getLexer().UnLex(Tok);
+    return Error(getTok().getLoc(), "either pre-decrement or post-increment expected");
+  }
+
+  EndLoc = Parser.getTok().getLoc();
+  return ParseStatus::Success;
+}
+
+ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
+  const AsmToken Tok = Parser.getTok();
+  const MCExpr *Expr;
+
   // Eat % and $ which are used in SuperH asm.
   if (Tok.is(AsmToken::Percent) || Tok.is(AsmToken::Dollar))
     Parser.Lex();
 
   if (Parser.parseExpression(Expr, EndLoc))
-    return ParseStatus::Failure;
+    return ParseStatus::NoMatch;
 
   if (Expr->evaluateAsAbsolute(Imm))
     return ParseStatus::Success;
 
-  return ParseStatus::Failure;
+  getLexer().UnLex(Tok);
+  return ParseStatus::NoMatch;
 }
 
-ParseStatus SuperHAsmParser::parseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc) {
-  const AsmToken &Tok = Parser.getTok();
-  StartLoc = Tok.getLoc();
-  EndLoc = Tok.getEndLoc();
 
-  Reg = matchRegisterName(Tok, RegKind);
-  if (Reg) {
-    Parser.Lex();
+
+//===----------------------------------------------------------------------===//
+//                            Parser Entrypoints
+//===----------------------------------------------------------------------===//
+
+ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
+  SMLoc StartLoc = getLexer().getLoc();
+  SMLoc EndLoc = getLexer().getLoc();
+
+  // Immediates are prefixed with a #
+  if (getTok().isNot(AsmToken::Hash)) {
+    return ParseStatus::NoMatch;
+  }
+  
+  int64_t Imm;
+  if (tryParseImm(Imm, StartLoc, EndLoc).isSuccess()) {
+    EndLoc = getLexer().getLoc();
+    Operands.push_back(SuperHOperand::CreateImm(
+      MCConstantExpr::create(Imm, getContext()), 
+      StartLoc, 
+      EndLoc
+    ));
     return ParseStatus::Success;
   }
-  return ParseStatus::Failure;
+
+  return ParseStatus::NoMatch;
 }
 
-ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
-  const AsmToken &Tok = Parser.getTok();
+ParseStatus SuperHAsmParser::parseDisp(OperandVector &Operands) {
+  return ParseStatus::NoMatch;
+}
+
+ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
+  const AsmToken Tok = Parser.getTok();
   SMLoc StartLoc = getLexer().getLoc();
   SMLoc EndLoc = getLexer().getLoc();
+  
+  // Parse register relative.
+  MCRegister BaseReg;
+  MCRegister OffReg;
+  const MCExpr *Offset;
+  if (tryParseRegRelative(BaseReg, OffReg, Offset, StartLoc, EndLoc).isNoMatch()) {
+    getLexer().UnLex(Tok);
+    return ParseStatus::NoMatch;
+  }
 
+  // Base register must be PC for this type.
+  if (BaseReg != SH::PC) {
+    getLexer().UnLex(Tok);
+    return ParseStatus::NoMatch;
+  }
 
-  switch(Tok.getKind()) {
-  default: {
-
-    // Try parsing as register first.
-    unsigned RegKind;
-    MCRegister Reg;
-    if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
-      Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
-      return ParseStatus::Success;
-    }
+  EndLoc = getLexer().getLoc();
+  Operands.push_back(SuperHOperand::CreateSymRef(Offset, StartLoc, EndLoc));
+  return ParseStatus::Success;
+}
 
-    // That failed, try parsing as expression.
-    const MCExpr *EVal;
-    if (Parser.parseExpression(EVal, EndLoc)) 
-      return ParseStatus::Failure;
+ParseStatus SuperHAsmParser::parseRegister(OperandVector &Operands) {
+  SMLoc StartLoc = getLexer().getLoc();
+  SMLoc EndLoc = getLexer().getLoc();
 
-    Operands.push_back(SuperHOperand::CreateFromExpr(EVal, StartLoc, EndLoc));
+  MCRegister Reg;
+  unsigned RegKind;
+  if (tryParseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+    Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
     return ParseStatus::Success;
   }
 
-  // Immediates.
-  case llvm::AsmToken::Hash: {
-    Parser.Lex();
-    int64_t Imm;
-    if (parseImm(Imm, StartLoc, EndLoc).isSuccess()) {
-      const MCExpr *Val = MCConstantExpr::create(Imm, getContext());
-      Operands.push_back(SuperHOperand::CreateImm(Val, StartLoc, EndLoc));
-      return ParseStatus::Success;
-    }
+  return ParseStatus::NoMatch;
+}
 
-    // Un-lex on error
-    getLexer().UnLex(Tok);
-    return ParseStatus::Failure;
+ParseStatus SuperHAsmParser::parseRegisterIndirect(OperandVector &Operands) {
+  const AsmToken Tok = Parser.getTok();
+  SMLoc StartLoc = getLexer().getLoc();
+  SMLoc EndLoc = getLexer().getLoc();
+
+  bool IsInc, IsDec;
+  MCRegister Reg;
+
+  ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
+  if (!Result.isSuccess())
+    return Result;
+
+  // We're only looking for base register indirect here.
+  if (!IsInc && !IsDec) {
+    EndLoc = getLexer().getLoc();
+    Operands.push_back(SuperHOperand::CreateIReg(Reg, StartLoc, EndLoc));
+    return ParseStatus::Success;
   }
 
-  // Indirect Memory Access.
-  case AsmToken::At: {
-    Parser.Lex();
+  getLexer().UnLex(Tok);
+  return ParseStatus::NoMatch;
+}
 
-    // Handle the different kinds of indirect memory access.
-    switch(Parser.getTok().getKind()) {
-    default: {
-      getLexer().UnLex(Tok);
-      return ParseStatus::Failure;
-    }
-    
-    // Handle Register Indirect with Pre-Decrement.
-    case AsmToken::Minus: {
-      Parser.Lex();
+ParseStatus SuperHAsmParser::parseRegisterIndirectInc(OperandVector &Operands) {
+  const AsmToken Tok = Parser.getTok();
+  SMLoc StartLoc = getLexer().getLoc();
+  SMLoc EndLoc = getLexer().getLoc();
 
-      unsigned RegKind;
-      MCRegister Reg;
-      if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
-        Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
-        return ParseStatus::Success;
-      }
+  bool IsInc, IsDec;
+  MCRegister Reg;
 
-      getLexer().UnLex(Tok);
-      return ParseStatus::Failure;
-    }
+  ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
+  if (!Result.isSuccess())
+    return Result;
+
+  // We're only looking for register indirect inc here.
+  if (IsInc && !IsDec) {
+    EndLoc = getLexer().getLoc();
+    Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
+    return ParseStatus::Success;
+  }
+
+  getLexer().UnLex(Tok);
+  return ParseStatus::NoMatch;
+}
 
-    // Register Indirect
-    case AsmToken::Identifier: {
+ParseStatus SuperHAsmParser::parseRegisterIndirectDec(OperandVector &Operands) {
+  const AsmToken Tok = Parser.getTok();
+  SMLoc StartLoc = getLexer().getLoc();
+  SMLoc EndLoc = getLexer().getLoc();
 
-      unsigned RegKind;
-      MCRegister Reg;
-      if (parseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+  bool IsInc, IsDec;
+  MCRegister Reg;
 
-        // Handle Register Indirect with Increment.
-        if (Parser.getTok().is(AsmToken::Plus)) {
-          Parser.Lex();
+  ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
+  if (!Result.isSuccess())
+    return Result;
 
-          Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
-          return ParseStatus::Success;
-        }
+  // We're only looking for register indirect dec here.
+  if (!IsInc && IsDec) {
+    EndLoc = getLexer().getLoc();
+    Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
+    return ParseStatus::Success;
+  }
 
-        Operands.push_back(SuperHOperand::CreateIReg(Reg, StartLoc, EndLoc));
-        return ParseStatus::Success;
-      }
+  getLexer().UnLex(Tok);
+  return ParseStatus::NoMatch;
+}
 
-      getLexer().UnLex(Tok);
-      return ParseStatus::Failure;
-    }
-    }
+ParseStatus SuperHAsmParser::parseDirective(AsmToken DirectiveID) {
+  StringRef IDVal = DirectiveID.getIdentifier();
 
-    // Un-lex on error
-    getLexer().UnLex(Tok);
-    return ParseStatus::Failure;
+  if (IDVal.starts_with(".gnu_attribute")) {
+    if (parseGNUAttribute(DirectiveID.getLoc()))
+      return ParseStatus::Success;
+  }
+  if (IDVal.equals_insensitive(".little")) {
+      return ParseStatus::Success;
   }
+  if (IDVal.equals_insensitive(".big")) {
+      return ParseStatus::Success;
   }
+  return ParseStatus::NoMatch;
 }
 
-bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) {
+ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
+  switch (getLexer().getKind()) {
+  default:
+    return ParseStatus::NoMatch;
+
+  case AsmToken::Identifier:
+    // Try to parse a register, fall through to the next case if it fails.
+    if (parseRegister(Operands).isSuccess()) {
+      Parser.Lex();
+      return ParseStatus::Success;
+    }
+    return ParseStatus::NoMatch;
+  }
+}
+
+bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Mnemonic, 
+                                       SMLoc NameLoc, OperandVector &Operands) {
 
   // Match mnemonic.
-  bool MS = SuperHCheckMnemonic(Name, this->getAvailableFeatures(), 0);
+  bool MS = SuperHCheckMnemonic(Mnemonic, this->getAvailableFeatures(), 0);
   if (!MS) {
     return Error(NameLoc, "invalid instruction mnemonic" + 
-      SuperHMnemonicSpellCheck(Name, getAvailableFeatures(), 0));
+      SuperHMnemonicSpellCheck(Mnemonic, getAvailableFeatures(), 0));
   }
 
   // Chomp name and add it to the operands.
-  Operands.push_back(SuperHOperand::CreateToken(Name, NameLoc));
-  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+  Operands.push_back(SuperHOperand::CreateToken(Mnemonic, NameLoc));
+  int OperandNum = -1;
+  while (getLexer().isNot(AsmToken::EndOfStatement)) {
+    OperandNum++;
+    if (OperandNum > 0) {
+      if (getLexer().is(AsmToken::Comma)) {
+        Parser.Lex();
+      }
+    }
+
+    ParseStatus Result = MatchOperandParserImpl(Operands, Mnemonic);
+    if (Result.isSuccess()) {
+      continue;
+    }
+
+    if (Result.isFailure()) {
+      SMLoc Loc = getLexer().getLoc();
+      Parser.eatToEndOfStatement();
+      return Error(Loc, "unexpected token");
+    }
     
     // Initial operand
     if (!parseOperand(Operands).isSuccess()) {
       SMLoc Loc = getLexer().getLoc();
+      Parser.eatToEndOfStatement();
       return Error(Loc, "unexpected token");
     }
-
-    // Followup operands.
-    while (getLexer().is(AsmToken::Comma)) {
-      Parser.Lex();
-
-      // Parse and remember operand.
-      if (!parseOperand(Operands).isSuccess()) {
-        SMLoc Loc = getLexer().getLoc();
-        return Error(Loc, "unexpected token");
-      }
-    }
   }
 
   // Consume EndOfStatement
@@ -609,15 +862,6 @@ bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Nam
   return false;
 }
 
-ParseStatus SuperHAsmParser::parseDirective(AsmToken DirectiveID) {
-  StringRef IDVal = DirectiveID.getIdentifier();
-  if (IDVal.starts_with(".gnu_attribute"))
-    parseGNUAttribute(DirectiveID.getLoc());
-  else
-    return ParseStatus::NoMatch;
-  return ParseStatus::Success;
-}
-
 bool SuperHAsmParser::parseGNUAttribute(SMLoc L) {
   int64_t Tag;
   int64_t IntegerValue;
@@ -633,6 +877,8 @@ bool SuperHAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                      OperandVector &Operands, MCStreamer &Out,
                                      uint64_t &ErrorInfo,
                                      bool MatchingInlineAsm) {
+  
+  LLVM_DEBUG(dbgs() << "matchAndEmitInstruction\n");
   MCInst Inst;
   unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
   switch(MatchResult) {
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
index 7596ece4b12ec..d5d415def0389 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -22,8 +22,7 @@ SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
                                  const MCTargetOptions &Options)
     : MCAsmInfoELF(Options) {
   this->IsLittleEndian = TheTriple.isLittleEndian();
-  this->CommentString = ";";
-  this->SeparatorString = "\n";
+  this->CommentString = "!";
   this->InternalSymbolPrefix = ".L";
   this->PrivateLabelPrefix = ".L";
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index 03809c4d7a31d..c68ba20059187 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -133,9 +133,8 @@ def SuperHAsmParser : AsmParser {
 def SuperHAsmParserVariant : AsmParserVariant {
   let Variant = 0;
   let Name = "GCC";
-  let SeparatorCharacters = " \t,()@-+";
-  let TokenizingCharacters = "[]*!#";
-  let CommentDelimiter = ";";
+  let TokenizingCharacters = "()+-@";
+  let CommentDelimiter = "!";
 }
 
 //===----------------------------------------------------------------------===//

>From c3ae4f973e4bf46fd30e8b39373b45dc2b4bc709 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 1 Sep 2026 09:20:37 +0200
Subject: [PATCH 25/67] Fix parseImm

---
 .../SuperH/AsmParser/SuperHAsmParser.cpp       | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 6e45a5388068e..80f8f7dd17c97 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -629,20 +629,16 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
 
 ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
   const AsmToken Tok = Parser.getTok();
-  const MCExpr *Expr;
 
   // Eat % and $ which are used in SuperH asm.
-  if (Tok.is(AsmToken::Percent) || Tok.is(AsmToken::Dollar))
+  if (getTok().is(AsmToken::Percent) || getTok().is(AsmToken::Dollar))
     Parser.Lex();
 
-  if (Parser.parseExpression(Expr, EndLoc))
+  if (Parser.parseAbsoluteExpression(Imm)) {
+    getLexer().UnLex(Tok);
     return ParseStatus::NoMatch;
-
-  if (Expr->evaluateAsAbsolute(Imm))
-    return ParseStatus::Success;
-
-  getLexer().UnLex(Tok);
-  return ParseStatus::NoMatch;
+  }
+  return ParseStatus::Success;
 }
 
 
@@ -652,6 +648,7 @@ ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &E
 //===----------------------------------------------------------------------===//
 
 ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
+  const AsmToken Tok = Parser.getTok();
   SMLoc StartLoc = getLexer().getLoc();
   SMLoc EndLoc = getLexer().getLoc();
 
@@ -659,10 +656,10 @@ ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
   if (getTok().isNot(AsmToken::Hash)) {
     return ParseStatus::NoMatch;
   }
+  Parser.Lex();
   
   int64_t Imm;
   if (tryParseImm(Imm, StartLoc, EndLoc).isSuccess()) {
-    EndLoc = getLexer().getLoc();
     Operands.push_back(SuperHOperand::CreateImm(
       MCConstantExpr::create(Imm, getContext()), 
       StartLoc, 
@@ -671,6 +668,7 @@ ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
     return ParseStatus::Success;
   }
 
+  getLexer().UnLex(Tok);
   return ParseStatus::NoMatch;
 }
 

>From 9371ccbc9bf0af5b3a1ae046c05217838d3e2eea Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 1 Sep 2026 12:17:17 +0200
Subject: [PATCH 26/67] Refactor InstPrinter

---
 .../SuperH/AsmParser/SuperHAsmParser.cpp      | 179 +++++++-----------
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |  45 ++++-
 .../SuperH/MCTargetDesc/SuperHInstPrinter.h   |   6 +
 llvm/lib/Target/SuperH/SuperH.td              |   2 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  65 +++++--
 5 files changed, 166 insertions(+), 131 deletions(-)

diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 80f8f7dd17c97..69500eceaaaa6 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -98,8 +98,6 @@ class SuperHAsmParser : public MCTargetAsmParser {
   ParseStatus parseOperand(OperandVector &Operands);
   ParseStatus parseRegister(OperandVector &Operands);
   ParseStatus parseRegisterIndirect(OperandVector &Operands);
-  ParseStatus parseRegisterIndirectInc(OperandVector &Operands);
-  ParseStatus parseRegisterIndirectDec(OperandVector &Operands);
   ParseStatus parsePCRel(OperandVector &Operands);
   ParseStatus parseImm(OperandVector &Operands);
   ParseStatus parseDisp(OperandVector &Operands);
@@ -192,8 +190,10 @@ class SuperHOperand : public MCParsedAsmOperand {
   bool isReg() const override { return Kind == k_Register; }
   bool isDisp() const { return Kind == k_Displacement; }
   bool isMem() const override { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec | k_IndirectIndex)) != 0; }
-  bool isIndirectReg() const { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec)) != 0; }
-  bool isAnyReg() const { return isReg() || isIndirectReg(); }
+  bool isIReg() const { return Kind == k_IndirectReg; }
+  bool isIRegInc() const { return Kind == k_IndirectRegInc; }
+  bool isIRegDec() const { return Kind == k_IndirectRegDec; }
+  bool isAnyReg() const { return isReg() || isIReg() || isIRegInc() || isIRegDec(); }
   bool isPCRel() const { return Kind == k_Displacement && Mem.Base == SH::PC; }
 
   SMLoc getStartLoc() const override { return StartLoc; }
@@ -378,18 +378,18 @@ class SuperHOperand : public MCParsedAsmOperand {
     }
 
     // Indirect register has @ prefix.
-    if (isIndirectReg())
+    if (isIReg())
       OS << "@";
     
     // Pre-decrement.
-    if (Kind == k_IndirectRegDec)
+    if (isIRegDec())
       OS << "-";
 
     // Register or other symbol.
     OS << StrFromLoc(this->getStartLoc(), this->getEndLoc());
 
     // Indirect Post-Increment.
-    if (Kind == k_IndirectRegInc)
+    if (isIRegInc())
       OS << "+";
   }
 };
@@ -450,18 +450,13 @@ bool SuperHAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &End
 
 ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) {
   unsigned RegKind;
-  const AsmToken &Tok = Parser.getTok();
+  const AsmToken Tok = Parser.getTok();
   StartLoc = Tok.getLoc();
   EndLoc = Tok.getEndLoc();
 
-  // SuperH Registers are in the form of an identifier.
-  Reg = SH::NoRegister;
-  if (getLexer().isNot(AsmToken::Identifier))
-    return ParseStatus::NoMatch;
-
   // Match.
   Reg = matchRegisterName(Tok, RegKind);
-  if (RegKind == SuperHOperand::rk_None)
+  if (Reg == SH::NoRegister)
     return ParseStatus::NoMatch;
 
   // Consume the register.
@@ -482,14 +477,9 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, unsigned &RegKind
   StartLoc = Tok.getLoc();
   EndLoc = Tok.getEndLoc();
 
-  // SuperH Registers are in the form of an identifier.
-  Reg = SH::NoRegister;
-  if (getLexer().isNot(AsmToken::Identifier))
-    return ParseStatus::NoMatch;
-
   // Match.
   Reg = matchRegisterName(Tok, RegKind);
-  if (RegKind == SuperHOperand::rk_None)
+  if (Reg == SH::NoRegister)
     return ParseStatus::NoMatch;
 
   // Consume the register.
@@ -526,16 +516,15 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
     return ParseStatus::Success;
   }
 
-  // Parse "@(" sequence
-  if (getTok().isNot(AsmToken::At))
-    return ParseStatus::NoMatch;
-  Parser.Lex();
+  AsmToken Buf[2];
+  getLexer().peekTokens(Buf);
 
-  if (getTok().isNot(AsmToken::LParen)) {
-    getLexer().UnLex(Tok);
+  // Parse "@(" sequence
+  if (Buf[0].isNot(AsmToken::At) && Buf[1].isNot(AsmToken::LParen)) {
     return ParseStatus::NoMatch;
   }
   Parser.Lex();
+  Parser.Lex();
 
   // Parse identifier
   if (getTok().is(AsmToken::Identifier)) {
@@ -550,35 +539,30 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
   } else if (getTok().is(AsmToken::Integer)) {
 
     // Try parsing numeric displacements.
-    if (Parser.parseExpression(Offset, EndLoc)) {
-      getLexer().UnLex(Tok);
-      return ParseStatus::NoMatch;
-    }
+    int64_t Disp;
+    ParseStatus Result = tryParseImm(Disp, StartLoc, EndLoc);
+    if (!Result.isSuccess())
+      return Result;
+
+    Offset = MCConstantExpr::create(Disp, getContext());
   } else {
-    getLexer().UnLex(Tok);
-    return ParseStatus::NoMatch;
+
+    return Error(getTok().getLoc(), "expected identifier, register or displacement");
   }
 
   // Parse seperator
-  if (getTok().isNot(AsmToken::Comma)) {
-    getLexer().UnLex(Tok);
-    return ParseStatus::NoMatch;
-  }
-  Parser.Lex();
+  if (parseToken(AsmToken::Comma, "expected ','"))
+    return ParseStatus::Failure;
 
   // Parse base register
-  if (tryParseRegister(BaseReg, RegKind, StartLoc, EndLoc).isNoMatch()) {
-    getLexer().UnLex(Tok);
-    return ParseStatus::NoMatch;
-  }
+  ParseStatus Result = tryParseRegister(BaseReg, RegKind, StartLoc, EndLoc);
+  if (!Result.isSuccess())
+    return ParseStatus::Failure;
 
   // Whoops! missing ending parenthesis.
-  if (getTok().isNot(AsmToken::RParen)) {
-    getLexer().UnLex(Tok);
-    return ParseStatus::NoMatch;
-  }
+  if (parseToken(AsmToken::RParen, "expected ')'"))
+    return ParseStatus::Failure;
 
-  Parser.Lex();
   return ParseStatus::Success;
 }
 
@@ -594,27 +578,21 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
   SMLoc E = EndLoc;
   unsigned RegKind;
 
-  if (getTok().isNot(AsmToken::At))
+  if (!Parser.parseOptionalToken(AsmToken::At))
     return ParseStatus::NoMatch;
-  Parser.Lex();
 
   // Parse possible pre-decement
-  if (getTok().is(AsmToken::Minus)) {
+  if (Parser.parseOptionalToken(AsmToken::Minus))
     IsDec = true;
-    Parser.Lex();
-  }
 
   // Parse Register
-  if (tryParseRegister(Reg, RegKind, S, E).isNoMatch()) {
-    getLexer().UnLex(Tok);
-    return ParseStatus::NoMatch;
+  if (!tryParseRegister(Reg, RegKind, S, E).isSuccess()) {
+    return ParseStatus::Failure;
   }
 
   // Parse possible post-increment
-  if (Tok.is(AsmToken::Plus)) {
+  if (Parser.parseOptionalToken(AsmToken::Plus))
     IsInc = true;
-    Parser.Lex();
-  }
 
   // You can't do both increment and decrement.
   // this is just a straight up syntax error.
@@ -638,6 +616,8 @@ ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &E
     getLexer().UnLex(Tok);
     return ParseStatus::NoMatch;
   }
+
+  EndLoc = Parser.getTok().getLoc();
   return ParseStatus::Success;
 }
 
@@ -648,15 +628,14 @@ ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &E
 //===----------------------------------------------------------------------===//
 
 ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
+  LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
   const AsmToken Tok = Parser.getTok();
   SMLoc StartLoc = getLexer().getLoc();
   SMLoc EndLoc = getLexer().getLoc();
 
-  // Immediates are prefixed with a #
-  if (getTok().isNot(AsmToken::Hash)) {
+  // Immediates start with a '#'
+  if (!Parser.parseOptionalToken(AsmToken::Hash))
     return ParseStatus::NoMatch;
-  }
-  Parser.Lex();
   
   int64_t Imm;
   if (tryParseImm(Imm, StartLoc, EndLoc).isSuccess()) {
@@ -673,10 +652,12 @@ ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
 }
 
 ParseStatus SuperHAsmParser::parseDisp(OperandVector &Operands) {
+  LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
   return ParseStatus::NoMatch;
 }
 
 ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
+  LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
   const AsmToken Tok = Parser.getTok();
   SMLoc StartLoc = getLexer().getLoc();
   SMLoc EndLoc = getLexer().getLoc();
@@ -685,15 +666,13 @@ ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
   MCRegister BaseReg;
   MCRegister OffReg;
   const MCExpr *Offset;
-  if (tryParseRegRelative(BaseReg, OffReg, Offset, StartLoc, EndLoc).isNoMatch()) {
-    getLexer().UnLex(Tok);
-    return ParseStatus::NoMatch;
-  }
+  ParseStatus Result = tryParseRegRelative(BaseReg, OffReg, Offset, StartLoc, EndLoc);
+  if (!Result.isSuccess())
+    return Result;
 
   // Base register must be PC for this type.
   if (BaseReg != SH::PC) {
-    getLexer().UnLex(Tok);
-    return ParseStatus::NoMatch;
+    return Error(getTok().getLoc(), "expected PC-relative displacement");
   }
 
   EndLoc = getLexer().getLoc();
@@ -702,20 +681,27 @@ ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
 }
 
 ParseStatus SuperHAsmParser::parseRegister(OperandVector &Operands) {
-  SMLoc StartLoc = getLexer().getLoc();
-  SMLoc EndLoc = getLexer().getLoc();
+  LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
+  const AsmToken Tok = Parser.getTok();
+  SMLoc StartLoc = Tok.getLoc();
+  SMLoc EndLoc = Tok.getEndLoc();
 
   MCRegister Reg;
   unsigned RegKind;
   if (tryParseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
+    LLVM_DEBUG({
+      dbgs() << __FUNCTION__ << " (next): ";
+      getTok().dump(dbgs());
+      dbgs() << "\n";
+    });
     Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
     return ParseStatus::Success;
   }
-
   return ParseStatus::NoMatch;
 }
 
 ParseStatus SuperHAsmParser::parseRegisterIndirect(OperandVector &Operands) {
+  LLVM_DEBUG(dbgs() << __FUNCTION__ << "\n");
   const AsmToken Tok = Parser.getTok();
   SMLoc StartLoc = getLexer().getLoc();
   SMLoc EndLoc = getLexer().getLoc();
@@ -727,60 +713,30 @@ ParseStatus SuperHAsmParser::parseRegisterIndirect(OperandVector &Operands) {
   if (!Result.isSuccess())
     return Result;
 
-  // We're only looking for base register indirect here.
+  // Indirect
   if (!IsInc && !IsDec) {
+
     EndLoc = getLexer().getLoc();
     Operands.push_back(SuperHOperand::CreateIReg(Reg, StartLoc, EndLoc));
     return ParseStatus::Success;
   }
 
-  getLexer().UnLex(Tok);
-  return ParseStatus::NoMatch;
-}
-
-ParseStatus SuperHAsmParser::parseRegisterIndirectInc(OperandVector &Operands) {
-  const AsmToken Tok = Parser.getTok();
-  SMLoc StartLoc = getLexer().getLoc();
-  SMLoc EndLoc = getLexer().getLoc();
-
-  bool IsInc, IsDec;
-  MCRegister Reg;
-
-  ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
-  if (!Result.isSuccess())
-    return Result;
+  // Indirect Pre-Decrement
+  if (!IsInc && IsDec) {
 
-  // We're only looking for register indirect inc here.
-  if (IsInc && !IsDec) {
     EndLoc = getLexer().getLoc();
-    Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
+    Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
     return ParseStatus::Success;
   }
 
-  getLexer().UnLex(Tok);
-  return ParseStatus::NoMatch;
-}
-
-ParseStatus SuperHAsmParser::parseRegisterIndirectDec(OperandVector &Operands) {
-  const AsmToken Tok = Parser.getTok();
-  SMLoc StartLoc = getLexer().getLoc();
-  SMLoc EndLoc = getLexer().getLoc();
-
-  bool IsInc, IsDec;
-  MCRegister Reg;
-
-  ParseStatus Result = tryParseRegIndirect(Reg, IsInc, IsDec, StartLoc, EndLoc);
-  if (!Result.isSuccess())
-    return Result;
+  // Indirect Post-Increment
+  if (IsInc && !IsDec) {
 
-  // We're only looking for register indirect dec here.
-  if (!IsInc && IsDec) {
     EndLoc = getLexer().getLoc();
-    Operands.push_back(SuperHOperand::CreateIRegDec(Reg, StartLoc, EndLoc));
+    Operands.push_back(SuperHOperand::CreateIRegInc(Reg, StartLoc, EndLoc));
     return ParseStatus::Success;
   }
 
-  getLexer().UnLex(Tok);
   return ParseStatus::NoMatch;
 }
 
@@ -806,12 +762,7 @@ ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
     return ParseStatus::NoMatch;
 
   case AsmToken::Identifier:
-    // Try to parse a register, fall through to the next case if it fails.
-    if (parseRegister(Operands).isSuccess()) {
-      Parser.Lex();
-      return ParseStatus::Success;
-    }
-    return ParseStatus::NoMatch;
+    return parseRegister(Operands);
   }
 }
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index fadac2158f630..b9190f15263f3 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -41,9 +41,47 @@ void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
   OS << StringRef(getRegisterName(Reg)).lower();
 }
 
+void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+  const MCOperand &Op = MI->getOperand(OpNo);
+  OS << Op.getImm();
+}
+
+void SuperHInstPrinter::printImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+  const MCOperand &Op = MI->getOperand(OpNo);
+  OS << "#" << Op.getImm();
+}
+
+void SuperHInstPrinter::printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+  const MCOperand &Op = MI->getOperand(OpNo);
+  OS << "@" << StringRef(getRegisterName(Op.getReg())).lower();
+}
+
+void SuperHInstPrinter::printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+  const MCOperand &Op = MI->getOperand(OpNo);
+  OS << "@" << StringRef(getRegisterName(Op.getReg())).lower() << "+";
+}
+
+void SuperHInstPrinter::printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+  const MCOperand &Op = MI->getOperand(OpNo);
+  OS << "@-" << StringRef(getRegisterName(Op.getReg())).lower();
+}
+
 void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address, 
-        unsigned OpNo, raw_ostream &O) {
-  printOperand(MI, OpNo, O);
+                                      unsigned OpNo, raw_ostream &O) {
+  const MCOperand &Op = MI->getOperand(OpNo);
+
+  // Print standalone symbol.
+  if (Op.isExpr()) {
+    if (const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op.getExpr())) {
+      O << SymOp->getSymbol().getName();
+      return;
+    }
+  }
+
+  // Print immediate value.
+  if (Op.isImm()) {
+    O << "@(" << Op.getImm() << ",pc)";
+  }
 }
 
 void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
@@ -52,7 +90,6 @@ void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_
 
 void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
   const MCOperand &Op = MI->getOperand(OpNo);
-  
 
   // Print Register
   if (Op.isReg()) {
@@ -62,7 +99,7 @@ void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostrea
 
   // Print immediates
   if (Op.isImm()) {
-    O << Op.getImm();
+    O << "#" << Op.getImm();
     return;
   }
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index f22b48ac733b8..ea462c6087c49 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -48,7 +48,13 @@ class SuperHInstPrinter : public MCInstPrinter {
 private:
   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
   void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
+  void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostream &O);
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index c68ba20059187..eb404c67e61b5 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -133,7 +133,7 @@ def SuperHAsmParser : AsmParser {
 def SuperHAsmParserVariant : AsmParserVariant {
   let Variant = 0;
   let Name = "GCC";
-  let TokenizingCharacters = "()+-@";
+  let TokenizingCharacters = "()+-@#";
   let CommentDelimiter = "!";
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 6826583a17c80..98b3fd921a5a4 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -96,20 +96,30 @@ class SHOpClass<string name,
 
 // Immediates
 class SHImmClass<int width> : SHOpClass<"Imm" # width> {
-    let PredicateMethod = "isImm";
-    let RenderMethod = "addImmOperands";
+  let PredicateMethod = "isImm";
+  let ParserMethod = "parseImm";
+  let RenderMethod = "addImmOperands";
 }
 
 // Displacements
 class SHDispClass<int width> : SHOpClass<"Disp" # width> {
-    let PredicateMethod = "isDisp";
-    let RenderMethod = "addDispOperands";
+  let PredicateMethod = "isDisp";
+  let ParserMethod = "parseDisp";
+  let RenderMethod = "addDispOperands";
 }
 
-// Memory Ops
-def SHMemClass : SHOpClass<"Mem"> {
-  let PredicateMethod = "isMem";
-  let RenderMethod = "addMemOperands";
+// PC-Relative Addressing
+class SHPCRelClass : SHOpClass<"PCRel"> {
+  let PredicateMethod = "isPCRel";
+  let ParserMethod = "parsePCRel";
+  let RenderMethod = "addPCRelOperands";
+}
+
+// Register Indirect Ops
+class SHRegIndirectClass<string op> : SHOpClass<"IReg" # op> {
+  let PredicateMethod = "isIReg" # op;
+  let ParserMethod = "parseRegisterIndirect";
+  let RenderMethod = "addIRegOperands";
 }
 
 //===--------------------------------------------------------------------------===//
@@ -121,6 +131,7 @@ class SHImmOp<int width, ValueType vt>
       : Operand<vt> {
     let ParserMatchClass = SHImmClass<width>;
     let OperandType = "OPERAND_IMMEDIATE";
+    let PrintMethod = "printImm";
     let MCOperandPredicate = [{int64_t Imm; return MCOp.evaluateAsConstantImm(Imm) ? isInt<}] # width # [{>(Imm) : false;}];
 }
 def imm8 : SHImmOp<8, i32>, ImmLeaf<i32, [{ return isInt<8>(Imm); }]>;
@@ -130,6 +141,7 @@ class SHDispOp<int width, ValueType vt>
       : Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
     let ParserMatchClass = SHDispClass<width>;
     let OperandType = "OPERAND_IMMEDIATE";
+    let PrintMethod = "printDisp";
     let MCOperandPredicate = [{
         int64_t Imm;
         if (MCOp.evaluateAsConstantImm(Imm))
@@ -141,7 +153,28 @@ def disp4   : SHDispOp<4, i4>;
 def disp8   : SHDispOp<8, i8>;
 def disp12  : SHDispOp<12, i16>;
 
+// PC-Relative Adressing
+class SHPCRelOp<int width, ValueType vt>
+      : Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
+  let ParserMatchClass = SHPCRelClass<>;
+  let OperandType = "OPERAND_PCREL";
+  let EncoderMethod = "getPCRelOpValue";
+  let DecoderMethod = "DecodePCRelDisp";
+  let PrintMethod = "printPCRelImm";
+    let MCOperandPredicate = [{
+        int64_t Imm;
+        if (MCOp.evaluateAsConstantImm(Imm))
+            return isUInt<#width>(Imm);
+        return MCOp.isBareSymbolRef();
+    }];
+}
+
+def pcrel8       : SHPCRelOp<8, i8>;
+def pcrel12      : SHPCRelOp<12, i16>;
+
+// Branch Targets
 def brtarget       : Operand<OtherVT> {
+  let ParserMatchClass = SHPCRelClass<>;
   let EncoderMethod = "getBranchTargetOpValue";
   let DecoderMethod = "DecodeBranchTarget";
   let PrintMethod = "printPCRelImm";
@@ -153,13 +186,21 @@ def cpinst_operand : Operand<i32> {
   let PrintMethod = "printCPInstOperand";
 }
 
-// Memory
-class SHMemRegOp<RegisterClass regClass> 
+// Register Indirect
+class SHIndirectRegOp<RegisterClass regClass, string op> 
       : RegisterOperand<regClass> {
-    let ParserMatchClass = SHMemClass;
+    let ParserMatchClass = SHRegIndirectClass<op>;
     let OperandType = "OPERAND_MEMORY";
+    let PrintMethod = "printIReg" # op;
 }
-def GPRMem : SHMemRegOp<GPR>;
+def IGPR    : SHIndirectRegOp<GPR, "">;
+def IGPRInc : SHIndirectRegOp<GPR, "Inc">;
+def IGPRDec : SHIndirectRegOp<GPR, "Dec">;
+
+// Addressing mode pattern reg+imm6
+let WantsRoot = true in
+def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
+
 
 //===--------------------------------------------------------------------------===//
 // Predicates

>From 613825e8524dab0767e9e40e439299092da00aa9 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 2 Sep 2026 04:24:04 +0200
Subject: [PATCH 27/67] Refactor register name getter

---
 .../Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp | 12 ++++++++----
 .../Target/SuperH/MCTargetDesc/SuperHInstPrinter.h   |  4 +++-
 llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp          |  8 +++++---
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index b9190f15263f3..22fc26b77b3e7 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -37,8 +37,12 @@ namespace llvm {
 SuperHInstPrinter::SuperHInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
                     const MCRegisterInfo &MRI) : MCInstPrinter(MAI, MII, MRI) {}
 
+const std::string SuperHInstPrinter::getRegName(MCRegister Reg) {
+  return StringRef(getRegisterName(Reg)).lower();
+}
+
 void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
-  OS << StringRef(getRegisterName(Reg)).lower();
+  OS << getRegName(Reg);
 }
 
 void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
@@ -53,17 +57,17 @@ void SuperHInstPrinter::printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O
 
 void SuperHInstPrinter::printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
-  OS << "@" << StringRef(getRegisterName(Op.getReg())).lower();
+  OS << "@" << getRegName(Op.getReg());
 }
 
 void SuperHInstPrinter::printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
-  OS << "@" << StringRef(getRegisterName(Op.getReg())).lower() << "+";
+  OS << "@" << getRegName(Op.getReg()) << "+";
 }
 
 void SuperHInstPrinter::printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
-  OS << "@-" << StringRef(getRegisterName(Op.getReg())).lower();
+  OS << "@-" << getRegName(Op.getReg());
 }
 
 void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address, 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index ea462c6087c49..17af288324675 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -39,13 +39,15 @@ class SuperHInstPrinter : public MCInstPrinter {
   void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
                                unsigned OpIdx, unsigned PrintMethodIdx,
                                const MCSubtargetInfo &STI, raw_ostream &O);
-  static const char *getRegisterName(MCRegister Reg);
 
   void printRegName(raw_ostream &OS, MCRegister Reg) override;
   void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
                  const MCSubtargetInfo &STI, raw_ostream &OS) override;
 
+  static const std::string getRegName(MCRegister Reg);
+
 private:
+  static const char *getRegisterName(MCRegister Reg);
   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
 
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index 884266d52eff9..d3dc1cad8ba3f 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -70,8 +70,8 @@ class SuperHAsmPrinter : public AsmPrinter {
   void emitConstantPool() override { }
   void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
 
-  static const char *getRegisterName(MCRegister Reg) {
-    return SuperHInstPrinter::getRegisterName(Reg);
+  static std::string getRegisterName(MCRegister Reg) {
+    return SuperHInstPrinter::getRegName(Reg);
   }
 
   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -118,7 +118,7 @@ void SuperHAsmPrinter::printOperand(const MachineInstr *MI, int OpNo, raw_ostrea
 
   switch (MO.getType()) {
   case MachineOperand::MO_Register:
-    O << StringRef(getRegisterName(MO.getReg())).lower();
+    O << getRegisterName(MO.getReg());
     break;
   case MachineOperand::MO_Immediate:
     O << MO.getImm();
@@ -177,6 +177,8 @@ bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned Op
 void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
   const DataLayout &DL = getDataLayout();
   int Size = DL.getTypeAllocSize(MCPV->getType());
+  if (Size < 4)
+    Size = 4;
 
   MCSymbol *MCSym;
   SuperHConstantPoolValue *SCPV = static_cast<SuperHConstantPoolValue*>(MCPV);

>From 87dff3aa266d16670d82ac3dfe2fe002b2aff125 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 2 Sep 2026 04:24:36 +0200
Subject: [PATCH 28/67] Remove duplicate error messages from
 MatchOperandParserImpl

---
 .../lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 69500eceaaaa6..210d023b71dee 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -597,8 +597,7 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
   // You can't do both increment and decrement.
   // this is just a straight up syntax error.
   if (IsInc && IsDec) {
-    getLexer().UnLex(Tok);
-    return Error(getTok().getLoc(), "either pre-decrement or post-increment expected");
+    return Error(E, "either pre-decrement or post-increment expected");
   }
 
   EndLoc = Parser.getTok().getLoc();
@@ -689,11 +688,6 @@ ParseStatus SuperHAsmParser::parseRegister(OperandVector &Operands) {
   MCRegister Reg;
   unsigned RegKind;
   if (tryParseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
-    LLVM_DEBUG({
-      dbgs() << __FUNCTION__ << " (next): ";
-      getTok().dump(dbgs());
-      dbgs() << "\n";
-    });
     Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
     return ParseStatus::Success;
   }
@@ -792,10 +786,11 @@ bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Mne
       continue;
     }
 
+    // NOTE:  All the Failure states are Errors in of themselves,
+    //        as such we don't return an error in this branch.
     if (Result.isFailure()) {
-      SMLoc Loc = getLexer().getLoc();
       Parser.eatToEndOfStatement();
-      return Error(Loc, "unexpected token");
+      return true;
     }
     
     // Initial operand

>From 4018c6720d34eff71f9688100943553fa4655617 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 2 Sep 2026 04:30:37 +0200
Subject: [PATCH 29/67] Add error message for missing register operand

---
 llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 210d023b71dee..47a01005d4e46 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -557,7 +557,7 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
   // Parse base register
   ParseStatus Result = tryParseRegister(BaseReg, RegKind, StartLoc, EndLoc);
   if (!Result.isSuccess())
-    return ParseStatus::Failure;
+    return Error(StartLoc, "expected register");
 
   // Whoops! missing ending parenthesis.
   if (parseToken(AsmToken::RParen, "expected ')'"))
@@ -587,7 +587,7 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
 
   // Parse Register
   if (!tryParseRegister(Reg, RegKind, S, E).isSuccess()) {
-    return ParseStatus::Failure;
+    return Error(E, "expected register");
   }
 
   // Parse possible post-increment

>From 829a87436a22d7af0615ed6dd34d0741c20d5621 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 04:51:29 +0200
Subject: [PATCH 30/67] Switch .align to match GAS

---
 llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp | 6 ++++++
 llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h   | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
index d5d415def0389..6ea386dbc1825 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -25,4 +25,10 @@ SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
   this->CommentString = "!";
   this->InternalSymbolPrefix = ".L";
   this->PrivateLabelPrefix = ".L";
+  this->MinInstAlignment = 1;
+
+  // NOTE:  GAS SH Assembly uses Log2(N) alignment specifiers,
+  //        we replicate those here.
+  this->AlignmentIsInBytes = false;
+  this->HasFunctionAlignment = true;
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
index 0dfc47b66f766..232d952eb05f8 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
@@ -32,7 +32,7 @@ class SuperHMCAsmInfo : public MCAsmInfoELF {
 
 public:
 	explicit SuperHMCAsmInfo(const Triple &TheTriple,
-                             const MCTargetOptions &Options);
+                           const MCTargetOptions &Options);
 };
 
 namespace SH {

>From bfc6919924dfc1897105ff32b5cdbfa18c424a6d Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 04:52:09 +0200
Subject: [PATCH 31/67] Fix tryParseRegRelative token check

---
 llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index 47a01005d4e46..e4921dbac6cb5 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -516,11 +516,8 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
     return ParseStatus::Success;
   }
 
-  AsmToken Buf[2];
-  getLexer().peekTokens(Buf);
-
   // Parse "@(" sequence
-  if (Buf[0].isNot(AsmToken::At) && Buf[1].isNot(AsmToken::LParen)) {
+  if (getTok().isNot(AsmToken::At) || getLexer().peekTok().isNot(AsmToken::LParen)) {
     return ParseStatus::NoMatch;
   }
   Parser.Lex();

>From 77a98602930279bffa9bd303cc200725300a19f0 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 04:52:37 +0200
Subject: [PATCH 32/67] Align constpool entries to 32-bits

---
 llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
index 226136c6fd73f..8703f20fd2c1d 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
+++ b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
@@ -730,6 +730,7 @@ bool SuperHConstantIslands::handleConstantPoolUser(unsigned CPUserIndex,
     // We are adding new water.  Update NewWaterList.
     NewWaterList.insert(NewIsland);
   }
+
   // Always align the new block because CP entries can be smaller than 4
   // bytes. Be careful not to decrease the existing alignment, e.g. NewMBB may
   // be an already aligned constant pool block.
@@ -1101,7 +1102,7 @@ SuperHConstantIslands::doInitialConstPlacement(std::vector<MachineInstr *> &CPEM
   // move functions around based on their alignment.
   // Special case: halfword literals still need word alignment on the function.
   Align FuncAlign = MaxAlign;
-  if (MaxAlign == 2)
+  if (FuncAlign < 4)
     FuncAlign = Align(4);
   MF->ensureAlignment(FuncAlign);
 

>From 1a43d8fa8d1123e672debd88fd99810b8f5b19e9 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 04:53:16 +0200
Subject: [PATCH 33/67] Refactor loads and stores to use pseudo-op

---
 .../SuperH/MCTargetDesc/SuperHAsmBackend.cpp  | 113 +++++--
 .../SuperH/MCTargetDesc/SuperHAsmBackend.h    |  18 +-
 .../MCTargetDesc/SuperHELFObjectWriter.cpp    |  17 +-
 .../MCTargetDesc/SuperHMCCodeEmitter.cpp      |  68 ++--
 llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp   |  18 +-
 llvm/lib/Target/SuperH/SuperHCallingConv.td   |   4 +-
 .../Target/SuperH/SuperHConstantPoolValue.cpp |   6 +-
 .../Target/SuperH/SuperHConstantPoolValue.h   |   1 -
 .../Target/SuperH/SuperHFillDelaySlots.cpp    |   2 +-
 .../lib/Target/SuperH/SuperHFrameLowering.cpp | 121 ++++---
 llvm/lib/Target/SuperH/SuperHFrameLowering.h  |   3 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  75 ++---
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 298 +++++++++++++----
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |  13 +-
 llvm/lib/Target/SuperH/SuperHInstrFormats.td  |  18 ++
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 179 ++++++++++-
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |  15 +
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 301 ++++++++++++------
 llvm/lib/Target/SuperH/SuperHMCInstLower.cpp  |   7 +-
 .../SuperH/SuperHMachineFunctionInfo.cpp      |   4 +-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp |  37 ++-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.td  |  40 ++-
 22 files changed, 1001 insertions(+), 357 deletions(-)

diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index ae24d50d921b8..878d658f9e7f3 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -19,6 +19,7 @@
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCFixup.h"
 #include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCValue.h"
 #include "llvm/Support/CommandLine.h"
@@ -29,14 +30,15 @@
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdint>
+#include <optional>
 
 using namespace llvm;
 
-SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
+SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) : 
+                  MCAsmBackend(STI.getTargetTriple().isLittleEndian()
                          ? llvm::endianness::little
                          : llvm::endianness::big),
-      STI(STI), OSABI(OSABI) {
-
+                  STI(STI), OSABI(OSABI) {
 }
 
 bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
@@ -47,7 +49,7 @@ bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
   // text section (otherwise we have unaligned instructions, and thus have
   // far bigger problems), so just write NOP instructions.
   uint64_t NumNops = Count / 2;
-  for (uint64_t i = 0; i != NumNops; ++i)
+  for (uint64_t i = 0; i != NumNops; i++)
     support::endian::write(OS, SHNopEnc, Endian);
 
   // Write any straggling zeros needed.
@@ -129,47 +131,61 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
   return Infos[Kind - FirstTargetFixupKind];
 }
 
-void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
-                                 const MCValue &Target, uint8_t *Data,
-                                 uint64_t Value, bool IsResolved) {
-  
-  // Handle Relocations
-  IsResolved = tryAddReloc(F, Fixup, Target, Value, IsResolved);
-  MCFixupKind Kind = Fixup.getKind();
-  if (mc::isRelocation(Kind)) 
-    return;
+std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup &Fixup,
+                                                    MCValue &Target, uint64_t &FixedValue) {
+  return {};
+}
 
-  // Handle non-relocations
-  MCContext &Ctx = getContext();
-  MCFixupKindInfo Info = getFixupKindInfo(Kind);
-  if (!Value)
-    return; // No encoding change.
+unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
+                                            const MCValue &Target, uint64_t Value,
+                                            bool IsResolved, MCContext &Ctx,
+                                            const MCSubtargetInfo *STI) const {
+  unsigned Kind = Fixup.getKind();
+  int64_t Addend = Target.getConstant();
 
-  unsigned NumBits = Info.TargetSize + Info.TargetOffset;
-  unsigned NumBytes = (NumBits / 8) + ((NumBits % 8) == 0 ? 0 : 1);
-  assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
-         "Invalid fixup offset!");
+  switch (Kind) {
+  default:
+    return Value;
 
-  // Flip the bits if neccesary, then spit them out
-  Value <<= Info.TargetOffset;
-  bool SwapValue = Endian == llvm::endianness::big;
-  for (unsigned i = 0; i < NumBytes; ++i) {
-    unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
-    uint8_t mask = (((Value >> (i * 8)) & 0xff));
-    Data[Idx] |= mask;
+  case SH::fixup_got_low16:
+    return (Value+Addend) & 65535;
+
+  case SH::fixup_got_medlow16:
+    return ((Value+Addend) >> 16) & 65535;
+
+  case SH::fixup_got_medhi16:
+    return ((Value+Addend) >> 32) & 65535;
+
+  case SH::fixup_got_hi16:
+    return ((Value+Addend) >> 48) & 65535;
+
+  case SH::fixup_got10by4:
+    return (Value+Addend) / 4;
+
+  case SH::fixup_got10by8:
+    return (Value+Addend) / 8;
+
+  case SH::fixup_relative:
+  case SH::fixup_relative64:
+    return Value+Addend;
+
+  case SH::fixup_dir32:
+    return (Value+Addend);
+
+  case SH::fixup_rel32:
+    return Value+Addend;
   }
 }
 
 bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
                                const MCValue &Target, uint64_t &FixedValue,
                                bool IsResolved) {
-  
   MCValue PCITarget; // PC-Indirect Target
 
   // Get indirect target location.
   switch(Fixup.getKind()) {
   default: 
-    return {};
+    return false;
 
   case FK_Data_1:
   case FK_Data_2:
@@ -186,7 +202,7 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
   if (!PCITarget.getAddSym())
     return false;
 
-  // Evaluate as ELF.
+  // Evaluate addend as ELF.
   auto &SA = static_cast<const MCSymbolELF &>(*PCITarget.getAddSym());
   if (SA.isUndefined())
     return false;
@@ -209,6 +225,39 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
   return true;
 }
 
+void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
+                                 const MCValue &Target, uint8_t *Data,
+                                 uint64_t Value, bool IsResolved) {
+  
+  // Handle Relocations
+  IsResolved = tryAddReloc(F, Fixup, Target, Value, IsResolved);
+  MCFixupKind Kind = Fixup.getKind();
+  if (mc::isRelocation(Kind)) 
+    return;
+
+  // Handle non-relocations
+  MCContext &Ctx = getContext();
+  MCFixupKindInfo Info = getFixupKindInfo(Kind);
+  Value = adjustFixupValue(*Asm, Fixup, Target, Value, IsResolved, 
+                           Ctx, getSubtargetInfo(F));
+
+  if (!Value)
+    return; // No encoding change.
+
+  unsigned NumBits = Info.TargetSize + Info.TargetOffset;
+  unsigned NumBytes = (NumBits / 8) + ((NumBits % 8) == 0 ? 0 : 1);
+  assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
+         "Invalid fixup offset!");
+
+  // Flip the bits if neccesary, then spit them out
+  Value <<= Info.TargetOffset;
+  bool SwapValue = Endian == llvm::endianness::big;
+  for (unsigned i = 0; i < NumBytes; ++i) {
+    unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
+    Data[Idx] |= uint8_t(((Value >> (i * 8)) & 0xff));
+  }
+}
+
 std::unique_ptr<MCObjectTargetWriter> 
 SuperHAsmBackend::createObjectTargetWriter() const {
   return createSuperHELFObjectWriter(OSABI);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
index f27ed3891217b..833e1247b152a 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
@@ -31,17 +31,27 @@ class SuperHAsmBackend : public MCAsmBackend {
 
   std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
   MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
+
   void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
                   uint8_t *Data, uint64_t Value, bool IsResolved) override;
-  bool tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
-                               const MCValue &Target, uint64_t &FixedValue,
-                               bool IsResolved);
+  std::optional<bool> evaluateFixup(const MCFragment &, MCFixup &, MCValue &,
+                                    uint64_t &) override;
 	
 	std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override;
-
+  
   bool writeNopData(raw_ostream &OS, uint64_t Count,
                     const MCSubtargetInfo *STI) const override;
+  
+
+  bool tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
+                               const MCValue &Target, uint64_t &FixedValue,
+                               bool IsResolved);
+
+  unsigned adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
+                            const MCValue &Target, uint64_t Value,
+                            bool IsResolved, MCContext &Ctx,
+                            const MCSubtargetInfo *STI) const;
 };
 } // namespace llvm
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index 20c6718e399ce..292d55241e814 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -50,9 +50,19 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
   switch ((unsigned)Fixup.getKind()) { 
   case FK_Data_1:
   case FK_Data_2:
-  case FK_Data_4:
   case FK_Data_8:
-    return ELF::R_SH_NONE;
+    return 0;
+  
+  case FK_Data_4: {
+    switch (Spec) {
+    case SH::S_None:
+      return ELF::R_SH_DIR32;
+    case SH::S_PCREL:
+      return ELF::R_SH_REL32;
+    default:
+      return SH::S_DIR;
+    }
+  }
 
   case SH::fixup_got32:
     return ELF::R_SH_GOT32;
@@ -172,7 +182,8 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
 
 bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
                                                    unsigned Type) const {
-  return true;
+
+  return false;
 }
 
 std::unique_ptr<MCObjectTargetWriter>
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 55383441344a5..8d6c613eef9bf 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -12,15 +12,14 @@
 
 
 #include "SuperHFixupKinds.h"
-#include "SuperHMCAsmInfo.h"
 #include "SuperHMCTargetDesc.h"
 #include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/bit.h"
-#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/TargetRegistry.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCFixup.h"
@@ -30,15 +29,14 @@
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/DebugLog.h"
 #include "llvm/Support/EndianStream.h"
+#include "llvm/Support/ErrorHandling.h"
 #include <cstdint>
 
 
 using namespace llvm;
 
-#define DEBUG_TYPE "mccodeemitter"
+#define DEBUG_TYPE "sh-mccodeemitter"
 
 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
 
@@ -70,11 +68,15 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
 
-  unsigned getBranchTargetOpValue(const MCInst &MI, const MCExpr *Expr,
+  unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
 
-  unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
+  unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+                          SmallVectorImpl<MCFixup> &Fixups,
+                          const MCSubtargetInfo &STI) const;
+
+  unsigned getPCRelOpValue(const MCInst &MI, unsigned OpNo,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
 
@@ -122,7 +124,6 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
                                            SmallVectorImpl<char> &CB,
                                            SmallVectorImpl<MCFixup> &Fixups,
                                            const MCSubtargetInfo &STI) const {
-
   uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
 
   // NOTE:  All base instructions are 16-bit in SH ASM
@@ -141,11 +142,16 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
   ++MCNumEmitted;
 }
 
-unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, 
-                                                     const MCExpr *Expr,
+unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                                                      SmallVectorImpl<MCFixup> &Fixups,
                                                      const MCSubtargetInfo &STI) const {
-  return getExprOpValue(MI, Expr, Fixups, STI);
+  return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
+}
+
+unsigned SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
+                                              SmallVectorImpl<MCFixup> &Fixups,
+                                              const MCSubtargetInfo &STI) const {
+  return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
 }
 
 unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
@@ -156,13 +162,21 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
 
   MCExpr::ExprKind Kind = Expr->getKind();
 
-  // Binary Op
-  if (Kind == MCExpr::Binary) {
-    Expr = static_cast<const MCBinaryExpr *>(Expr)->getLHS();
-    Kind = Expr->getKind();
+  switch(Kind) {
+  case MCExpr::ExprKind::Binary: {
+    unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI);
+    Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI);
+    return Res;
   }
-
-  if (Kind == MCExpr::SymbolRef) {
+  case MCExpr::ExprKind::Target: {
+    llvm_unreachable("TODO"); 
+  }
+  case MCExpr::ExprKind::Specifier: {
+    const MCSpecifierExpr *Spec = static_cast<const MCSpecifierExpr *>(Expr);
+    Fixups.push_back(MCFixup::create(0, Spec, Spec->getSpecifier()));
+    return 0;
+  }
+  case MCExpr::ExprKind::SymbolRef: {
 
     // NOTE:  A few (DSP and SH2A) instructions are 32-bits wide.
     //        We handle those quite crudely.
@@ -170,21 +184,23 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
     Fixups.push_back(MCFixup::create(0, Expr, isOpcode32(OpCode) ? FK_Data_4 : FK_Data_2, true));
     return 0;
   }
-
-  // Constant immediate.
-  int64_t Result;
-  if (Expr->evaluateAsAbsolute(Result))
-    return Result;
-
-  return 0;
+  case MCExpr::ExprKind::Constant: {
+    const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
+    return Const->getValue();
+  }
+  default:
+    llvm_unreachable("expression not supported!");
+  }
 }
 
+/// getMachineOpValue - Return binary encoding of operand. If the machine
+/// operand requires relocation, record the relocation and return zero.
 unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI, 
                              const MCOperand &MO,
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const {
   if (MO.isReg())
-      return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
+    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
 
   if (MO.isImm())
     return MO.getImm();
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index d3dc1cad8ba3f..567fcc79a3e0d 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -21,6 +21,7 @@
 #include "SuperHMCInstLower.h"
 #include "TargetInfo/SuperHTargetInfo.h"
 #include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -96,14 +97,16 @@ bool SuperHAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
 
 // Convert a SuperH-specific constant pool modifier into the associated
 // specifier.
-static uint8_t getSpecifierFromModifier(SHCP::SHCPModifier Modifier) {
+static uint8_t getModifierSpecifier(SHCP::SHCPModifier Modifier) {
   switch (Modifier) {
-  case SHCP::SHCPModifier::DIR:
-  case SHCP::SHCPModifier::no_modifier:
-    return SHII::MO_DIR;
-  default:
-    return SHII::MO_DIR;
+  case SHCP::no_modifier:
+    return SH::S_DIR;
+  case SHCP::GOT_PCREL:
+    return SH::S_GOT_PCREL;
+  case SHCP::DIR:
+    return SH::S_DIR;
   }
+  llvm_unreachable("Invalid SHCPModifier!");
 }
 
 
@@ -173,7 +176,6 @@ bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned Op
 //                                Constant Pool
 //===----------------------------------------------------------------------===//
 
-
 void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
   const DataLayout &DL = getDataLayout();
   int Size = DL.getTypeAllocSize(MCPV->getType());
@@ -197,7 +199,7 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
 
   // Create an MCSymbol for the reference.
   const MCExpr *Expr = MCSymbolRefExpr::create(
-    MCSym, 
+    MCSym,
     OutContext
   );
   OutStreamer->emitValue(Expr, Size);
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index 429bd8be41908..71d899d3c7e8b 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -15,7 +15,7 @@
 def CC_SH : CallingConv<[
 
   // All lower size parameters are promoted to 32-bit
-  CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+  CCIfType<[i1, i8, i16],  CCPromoteToType<i32>>,
   CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
 ]>;
 
@@ -29,7 +29,7 @@ def RetCC_SH : CallingConv<[
 
   // Anything that doesn't fit in registers should be spilled.
   CCIfType<[i32], CCAssignToStack<4, 4>>,
-  CCIfType<[i64], CCAssignToStack<8, 8>>,
+  CCIfType<[i64], CCAssignToStack<8, 4>>,
 ]>;
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
index 0b9d5eaf0701d..cdedd3e8f634b 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
@@ -40,9 +40,7 @@ StringRef SuperHConstantPoolValue::getModifierText() const {
   case SHCP::no_modifier:
     return "none";
   case SHCP::GOT_PCREL:
-    return "GOT_PCREL";
-  case SHCP::GOT_PLTOFF:
-    return "gotpltoff";
+    return "gotpcrel";
   case SHCP::DIR:
     return "";
   }
@@ -199,7 +197,7 @@ SuperHConstantPoolSymbol::SuperHConstantPoolSymbol(LLVMContext &C, StringRef s,
 
 SuperHConstantPoolSymbol *SuperHConstantPoolSymbol::Create(LLVMContext &C,
                                                      StringRef s, unsigned ID) {
-  return new SuperHConstantPoolSymbol(C, s, ID, SHCP::no_modifier);
+  return new SuperHConstantPoolSymbol(C, s, ID, SHCP::DIR);
 }
 
 int SuperHConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
index f606b1b6869b5..86f718ca381ce 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
@@ -41,7 +41,6 @@ namespace SHCP {
     no_modifier,  /// None
     DIR,          /// Direct
     GOT_PCREL,    /// Global Offset Table, PC Relative
-    GOT_PLTOFF,   /// Global Offset Table, Thread Pointer Offset
   };
 
 } // end namespace SHCP
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 8d092e0b570aa..10510a3e13183 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -114,7 +114,7 @@ bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
   MachineFunction &MF = *MBB.getParent();
   MachineInstr &MI = *MBBI;
 
-  if (auto *Candidate = SuperHFillDelaySlots::findSlotCandidate(MBB, MBBI)) {
+  if (auto *Candidate = findSlotCandidate(MBB, MBBI)) {
       LLVM_DEBUG(dbgs() << "Swapping " << TII->getName(MI.getOpcode()) 
                         << " and " << TII->getName(Candidate->getOpcode()) 
                         << " @ " << MBB.getParent()->getName() << "\n");
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 93baa923182da..e4341a2d59db7 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -26,6 +26,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/DebugLog.h"
 #include "llvm/Target/TargetMachine.h"
+#include <cstdint>
 
 #define DEBUG_TYPE "sh-framelowering"
 
@@ -58,16 +59,30 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
     return false;
 
   Register SP = RII.getStackRegister();
+  Register FP = RII.getFrameRegister();
 
-  if (AdjValue < 255) {
+  if (abs(AdjValue) < 255) {
 
-    // Fast path, emit a single immediate add.
-    //    Emit add #-(size),r15
-    BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
-      .addReg(SP)
-      .addImm((int)AdjValue);
+    if (AdjValue < 0) {
+
+      // Fast path, emit a single immediate add.
+      //    Emit add #-(size),r15
+      BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
+        .addReg(SP)
+        .addImm((int)AdjValue);
+      return true;
+    }
+
+    if (AdjValue > 0) {
+
+      // Fast path, emit a single immediate add.
+      //    Emit add #(size),r14
+      BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), FP)
+        .addReg(FP)
+        .addImm((int)AdjValue);
+      return true;
+    }
 
-    return true;
   }
 
   // Slow path, shift 8 bits at a time into r0.
@@ -115,67 +130,48 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
   const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
   const MCContext &Ctx = MF.getContext();
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
-  bool HasFP = hasFP(MF);
 
   Register SP = RII.getStackRegister();
   Register FP = RII.getFrameRegister();
   Register GOT = RII.getGOTRegister();
 
+  LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
+
   // Early exit if we have no frame pointer.
-  if (!HasFP) {
+  if (!hasFP(MF)) {
     return;
   }
 
-  // Realign stack
+  // Realign stack to 32-bit offsets.
   uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
   MFI.setStackSize(StackSize);
   
+  // Store GOT
   if (STI.isPositionIndependent()) {
-    // Position Independent Prologue
-
-    // 1. Store GOT to stack and load local GOT.
     if (auto *GOTSym = MF.getPICBaseSymbol()) {
       BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
         .addReg(GOT)
         .setMIFlag(MachineInstr::FrameSetup);
     }
+  }
 
-    // 2. Establish Stack Frame
-    //    mov.l r14, at -r15
-    //    add <stackadj>,r15
-    //    mov r15,r14
-    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), FP)
-      .addReg(SP)
-      .setMIFlag(MachineInstr::FrameSetup);
-    emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
-    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), SP)
-      .addReg(FP)
-      .setMIFlag(MachineInstr::FrameSetup);
-
-    // 4. Save return address to stack.
-    if (MFI.hasCalls()) {
-      BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
-        .addReg(SP)
-        .setMIFlag(MachineInstr::FrameSetup);
-    }
-
-  } else {
-    // Position Dependent Prologue
+  // Establish Stack Frame
+  //    mov.l r14, at -r15
+  //    add <stackadj>,r15
+  //    mov r15,r14
+  BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+    .addReg(FP)
+    .setMIFlag(MachineInstr::FrameSetup);
+  emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
+  BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+    .addReg(SP)
+    .setMIFlag(MachineInstr::FrameSetup);
 
-    // 1. Establish Frame Pointer
-    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
-      .addReg(FP)
+  // Save return address to stack.
+  if (MFI.hasCalls()) {
+    BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+      .addReg(SP)
       .setMIFlag(MachineInstr::FrameSetup);
-
-    // 2. Create new stack frame
-    emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
-
-    // 3. Save return address to stack.
-    if (MFI.hasCalls()) {
-      BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
-        .addReg(SP)
-        .setMIFlag(MachineInstr::FrameSetup);
-    }
   }
 }
 
@@ -184,6 +180,8 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
   Register SP = RII.getStackRegister();
   Register FP = RII.getFrameRegister();
 
+  LLVM_DEBUG(dbgs() << "Emitting epilogue...\n");
+
   // Early exit if we have no frame pointer.
   if (!hasFP(MF)) {
     return;
@@ -207,8 +205,15 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
     }
 
     // 2. Delete stack frame, restoring stack pointer.
-    if (StackSize > 0)
+    if (StackSize > 0) {
       emitSPAdj(MF, MBB, MBBI, StackSize);
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameDestroy);
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRminciRn), SP)
+        .addReg(FP)
+        .setMIFlag(MachineInstr::FrameDestroy);
+    }
 
   } else {
 
@@ -220,13 +225,24 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
     }
 
     // 2. Delete stack frame, restoring stack pointer.
-    if (StackSize > 0)
+    //    add <stackadj>,r14
+    //    mov r14,r15
+    //    mov.l @r15+,r14
+    if (StackSize > 0) {
       emitSPAdj(MF, MBB, MBBI, StackSize);
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameDestroy);
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRminciRn), SP)
+        .addReg(FP)
+        .setMIFlag(MachineInstr::FrameDestroy);
+    }
   }
 }
 bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
                                  ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
   
+  LLVM_DEBUG(dbgs() << "Spilling " << CSI.size() << " registers...\n");
   if (CSI.empty()) {
     return false;
   }
@@ -251,6 +267,7 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
 bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
                                    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
   
+  LLVM_DEBUG(dbgs() << "Restoring " << CSI.size() << " registers...\n");
   if (CSI.empty()) {
       return false;
   }
@@ -262,7 +279,9 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
   const TargetInstrInfo &TII = *STI.getInstrInfo();
   Register SP = RII.getStackRegister();
 
-  for (const CalleeSavedInfo &I : CSI) {
+
+  for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
+
     MCRegister Reg = I.getReg();
     BuildMI(MBB, MI, DL, TII.get(SH::MOVLRminciRn), SP)
       .addReg(Reg)
@@ -316,7 +335,7 @@ bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
 
 bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  return !MFI.hasVarSizedObjects();
+  return hasFP(MF) && !MFI.hasVarSizedObjects();
 }
 
 void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index 7a20234e7817c..66c3ff6eb6dce 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -29,7 +29,8 @@ class SuperHFrameLowering : public TargetFrameLowering {
     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
                           /*StackAlignment*/Align(4),
                           /*LocalAreaOffset*/0,
-                          /*TransAl*/Align(4)),
+                          /*TransAl*/Align(4),
+                          /*StackReal*/false),
       STI(STI) {}
   bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
   bool hasReservedCallFrame(const MachineFunction &MF) const override;
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 3b9e745b8d334..613e23fccb2d6 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -75,7 +75,7 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
                                     InlineAsm::ConstraintCode ConstraintCode,
                                     std::vector<SDValue> &OutOps) override;
   
-  bool SelectAddr(SDNode *Root, SDValue N, SDValue &Base, SDValue &Disp);
+  bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
 
 
   /// Return a target constant with the specified value of type i4.
@@ -107,7 +107,7 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
   bool trySelectFrameIndex(SDNode *N);
   bool trySelectWrapper(SDNode *N);
   bool trySelectCMP(SDNode *N);
-  bool trySelectBrcond(SDNode *N);
+  bool trySelectBRCOND(SDNode *N);
   bool trySelectSELECT_CC(SDNode *N);
 
   const SuperHSubtarget *Subtarget;
@@ -136,6 +136,23 @@ bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
   return false;
 }
 
+bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
+                                    SDValue &Disp) {
+  SDLoc dl(Op);
+  auto DL = CurDAG->getDataLayout();
+  MVT PtrVT = getTargetLowering()->getPointerTy(DL);
+
+  // if the address is a frame index get the TargetFrameIndex.
+  if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
+    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
+    Disp = CurDAG->getTargetConstant(0, dl, MVT::i8);
+
+    return true;
+  }
+
+  return false;
+}
+
 
 
 
@@ -151,26 +168,26 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
   SDValue N0 = N->getOperand(0);
 
-  // Global Addresses
-  if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
-    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+  // External Symbols
+  if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
     ReplaceNode(N, Res);
     return true;
   }
 
-  // External Symbols
-  if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
-    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+  // Global Addresses
+  if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
+    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
     ReplaceNode(N, Res);
     return true;
   }
 
   // Block Addresses
   if (auto *CPV = SFI->tryGetConstant((BlockAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
-    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0, SHII::MO_DIR);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, TGA);
+    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
     ReplaceNode(N, Res);
     return true;
   }
@@ -202,31 +219,31 @@ bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
     // TST would be faster in this case.
     if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
       if (C->getSExtValue() == 0) {
-        Res = CurDAG->getMachineNode(SH::TSTRmRn, DL, MVT::i32, LHS, LHS);
+        Res = CurDAG->getMachineNode(SH::TSTRmRn, DL, MVT::Glue, LHS, LHS);
         break;
       }
     }
-    Res = CurDAG->getMachineNode(SH::CMPEQRmRn, DL, MVT::i32, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPEQRmRn, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case ISD::SETUGE:
   case ISD::SETULT: {
-    Res = CurDAG->getMachineNode(SH::CMPHSRmRn, DL, MVT::i32, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPHSRmRn, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case ISD::SETOGE:
   case ISD::SETOLT: {
-    Res = CurDAG->getMachineNode(SH::CMPGERmRn, DL, MVT::i32, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPGERmRn, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case ISD::SETUGT:
   case ISD::SETULE: {
-    Res = CurDAG->getMachineNode(SH::CMPGTRmRn, DL, MVT::i32, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPGTRmRn, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case ISD::SETOGT:
   case ISD::SETOLE: {
-    Res = CurDAG->getMachineNode(SH::CMPHIRmRn, DL, MVT::i32, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPHIRmRn, DL, MVT::Glue, LHS, RHS);
     break;
   }
   }
@@ -240,18 +257,13 @@ bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
   return false;
 }
 
-bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
+bool SuperHDAGToDAGISel::trySelectBRCOND(SDNode *N) {
   SDValue Chain = N->getOperand(0);
   SDValue Dest = N->getOperand(1);
   ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
   SDValue Cmp = N->getOperand(3);
   SDLoc DL(N);
 
-  // NOTE:  The CMP instruction writes implicitly to the T bit of the status
-  //        register, as such, we need to add said copy to our chain to ensure
-  //        scheduling can handle it.
-  Chain = CurDAG->getCopyToReg(Chain, DL, SH::SR, Cmp, SDValue());
-
   // NOTE:  The comparisons just set the T bit, it's up to later instructions
   //        to interpret the T bit as positive or negative.
   MachineSDNode *Res = nullptr;
@@ -263,7 +275,7 @@ bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
   case ISD::SETUGT:
   case ISD::SETOGT:
     Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BTS : SH::BT, 
-          DL, MVT::Other, Dest, Chain);
+          DL, MVT::Other, Dest, Chain, Cmp);
     break;
   case ISD::SETNE:
   case ISD::SETULE:
@@ -271,7 +283,7 @@ bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
   case ISD::SETULT:
   case ISD::SETOLT:
     Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BFS : SH::BF, 
-          DL, MVT::Other, Dest, Chain);
+          DL, MVT::Other, Dest, Chain, Cmp);
     break;
   }
 
@@ -284,13 +296,6 @@ bool SuperHDAGToDAGISel::trySelectBrcond(SDNode *N) {
   return false;
 }
 
-bool SuperHDAGToDAGISel::trySelectSELECT_CC(SDNode *N) {
-  const SDValue &TrueV = N->getOperand(0);
-  const SDValue &FalseV = N->getOperand(1);
-  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
-  const SDValue &Cmp = N->getOperand(3);
-  return false;
-}
 
 
 
@@ -336,10 +341,8 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
     return trySelectWrapper(N);
   case SHISD::CMP:
     return trySelectCMP(N);
-  case SHISD::SELECT_CC:
-    return trySelectSELECT_CC(N);
   case SHISD::BRCOND:
-    return trySelectBrcond(N);
+    return trySelectBRCOND(N);
   default:
     return false;
   }
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 252bb5952524d..299285b73c5c4 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -13,6 +13,7 @@
 
 #include "SuperHISelLowering.h"
 #include "SuperHConstantPoolValue.h"
+#include "SuperHInstrInfo.h"
 #include "SuperHMachineFunctionInfo.h"
 #include "SuperHSelectionDAGInfo.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
@@ -24,18 +25,21 @@
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/DebugLog.h"
+#include "llvm/Support/ErrorHandling.h"
 
 using namespace llvm;
 
 #define DEBUG_TYPE "sh-lower"
 
-#define DEBUG_FN_PRINT() LDBG() << __PRETTY_FUNCTION__;
+#define DEBUG_FN_PRINT() LLVM_DEBUG(dbgs() << " - " << __PRETTY_FUNCTION__ << "\n");
 
 static bool RetCC_SuperH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
                                CCValAssign::LocInfo &LocInfo,
@@ -71,8 +75,11 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
       setLoadExtAction(N, VT, MVT::i1, Promote);
       setLoadExtAction(N, VT, MVT::i64, Expand);
     }
+
+    setTruncStoreAction(VT, MVT::i1, Promote);
   }
 
+
   // Division and remainders are multi-instruction sequences
   // on SuperH. Use a custom pass to lower those.
   for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
@@ -109,6 +116,13 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setMinFunctionAlignment(Align(4));
 }
 
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+//                                LOWERING
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+
 
 
 
@@ -116,9 +130,8 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
 //                        CONDITIONAL BRANCH LOWERING
 //===----------------------------------------------------------------------===//
 SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
-                                       SDValue &OutCC, SelectionDAG &DAG, SDLoc DL) const {
-  OutCC = DAG.getCondCode(CC);
-  return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, OutCC);
+                                       SelectionDAG &DAG, SDLoc DL) const {
+  return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, DAG.getCondCode(CC));
 }
 
 SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
@@ -129,12 +142,11 @@ SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) cons
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
   SDLoc DL(Op);
 
-  SDValue TargetCC;
-  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
+  SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i8);
 
   SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
   return DAG.getNode(SHISD::SELECT_CC, DL, Op.getValueType(), Ops);
-  
 }
 
 SDValue SuperHTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
@@ -143,8 +155,8 @@ SDValue SuperHTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
   SDLoc DL(Op);
 
-  SDValue TargetCC;
-  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
+  SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i8);
 
   SDValue TrueV = DAG.getConstant(1, DL, Op.getValueType());
   SDValue FalseV = DAG.getConstant(0, DL, Op.getValueType());
@@ -162,8 +174,9 @@ SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
   SDValue Dest = Op.getOperand(4);
   SDLoc DL(Op);
 
-  SDValue TargetCC;
-  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
+  SDValue TargetCC = DAG.getCondCode(CC);
+
   return DAG.getNode(SHISD::BRCOND, DL, MVT::Other, Chain, Dest, TargetCC, Cmp);
 }
 
@@ -182,8 +195,8 @@ SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
     auto PtrVT = getPointerTy(DAG.getDataLayout());
     auto DL = SDLoc(G);
 
-    SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
-    SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, OpFlags);
+    // SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
+    SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
   }
   return SDValue();
@@ -200,7 +213,7 @@ SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG)
     const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
     SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
 
-    SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags);
+    SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
   }
   return SDValue();
@@ -217,7 +230,7 @@ SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) c
     const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
     SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
 
-    SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT, OpFlags);
+    SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
   }
   return SDValue();
@@ -246,30 +259,55 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext());
   CCInfo.AnalyzeFormalArguments(Ins, CC_SH);
 
-  unsigned InIdx = 0;
-  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) {
-    CCValAssign &VA = ArgLocs[i];
-    SDValue Arg;
-    
+
+  SDValue ArgValue;
+  for (CCValAssign &VA : ArgLocs) {
+
+    // Arguments stored on registers.
     if (VA.isRegLoc()) {
-      Register VReg = RegInfo.createVirtualRegister(&SH::GPRRegClass);
-      MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
-      Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
-      if (VA.getLocInfo() != CCValAssign::Indirect) {
-        if (VA.getLocVT() == MVT::f32)
-          Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
-        else if (VA.getLocVT() != MVT::i32) {
-          Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
-                            DAG.getValueType(VA.getLocVT()));
-          Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
-        }
-        InVals.push_back(Arg);
-        continue;
+      EVT RegVT = VA.getLocVT();
+      const TargetRegisterClass *RC;
+      if (RegVT == MVT::i8) {
+        RC = &SH::GPRRegClass;
+      } else if (RegVT == MVT::i16) {
+        RC = &SH::GPRRegClass;
+      } else if (RegVT == MVT::i32) {
+        RC = &SH::GPRRegClass;
+      } else {
+        llvm_unreachable("Unknown argument type!");
       }
+
+      Register Reg = MF.addLiveIn(VA.getLocReg(), RC);
+      ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
+
+      // NOTE:  Clang should not promote any i8 or i16 to i32 but for safety the
+      //        following code will handle zexts or sexts generated by other
+      //        front ends. Otherwise:
+      switch (VA.getLocInfo()) {
+      default:
+        llvm_unreachable("Unknown loc info!");
+      case CCValAssign::Full:
+        break;
+      case CCValAssign::BCvt:
+        ArgValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), ArgValue);
+        break;
+      case CCValAssign::SExt:
+        ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,
+                               DAG.getValueType(VA.getValVT()));
+        ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
+        break;
+      case CCValAssign::ZExt:
+        ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,
+                               DAG.getValueType(VA.getValVT()));
+        ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
+        break;
+      }
+
+      InVals.push_back(ArgValue);
     } else {
-      // Try matching frame index.
-      assert(VA.isMemLoc());
 
+      // Only arguments passed on the stack should make it here.
+      assert(VA.isMemLoc());
       EVT LocVT = VA.getLocVT();
 
       // Create the frame index object for this incoming parameter.
@@ -281,27 +319,13 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
       SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DL));
       InVals.push_back(DAG.getLoad(LocVT, dl, Chain, FIN,
                                    MachinePointerInfo::getFixedStack(MF, FI)));
-
-    }
-
-    SDValue ArgValue =
-        DAG.getLoad(VA.getValVT(), dl, Chain, Arg, MachinePointerInfo());
-    InVals.push_back(ArgValue);
-
-    unsigned ArgIndex = Ins[InIdx].OrigArgIndex;
-    assert(Ins[InIdx].PartOffset == 0);
-    while (i + 1 != e && Ins[InIdx + 1].OrigArgIndex == ArgIndex) {
-      CCValAssign &PartVA = ArgLocs[i + 1];
-      unsigned PartOffset = Ins[InIdx + 1].PartOffset;
-      SDValue Address = DAG.getMemBasePlusOffset(
-          ArgValue, TypeSize::getFixed(PartOffset), dl);
-      InVals.push_back(DAG.getLoad(PartVA.getValVT(), dl, Chain, Address,
-                                   MachinePointerInfo()));
-      ++i;
-      ++InIdx;
     }
   }
 
+  // TODO: Handle varargs.
+  if (IsVarArg) {
+    llvm_unreachable("varargs are not yet supported!");
+  }
   return Chain;
 }
 
@@ -616,12 +640,172 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
     return LowerExternalSymbol(Op, DAG);
   case ISD::BlockAddress:
     return LowerBlockAddress(Op, DAG);
-  case ISD::SETCC:
-    return LowerBR_CC(Op, DAG);
-  case ISD::SELECT_CC:
-    return LowerBR_CC(Op, DAG);
   case ISD::BR_CC:
     return LowerBR_CC(Op, DAG);
+  case ISD::SETCC:
+    return LowerSETCC(Op, DAG);
+  case ISD::SELECT_CC:
+    return LowerSELECT_CC(Op, DAG);
   }
   return SDValue();
+}
+
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+//                                INSERTERS
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//                            Load/Store Lowering
+//===----------------------------------------------------------------------===//
+
+MachineBasicBlock *SuperHTargetLowering::insertLoad(MachineInstr &MI, 
+                                                    MachineBasicBlock *MBB) const {
+  DEBUG_FN_PRINT()
+  MachineFunction &MF = *MBB->getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+  const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
+
+  MachineOperand Dest = MI.getOperand(0);
+  MachineOperand Offset = MI.getOperand(1);
+
+  // Target index load.
+  if (Dest.isTargetIndex()) {
+
+  }
+  
+  MI.eraseFromParent();
+  return MBB;
+}
+
+MachineBasicBlock *SuperHTargetLowering::insertStore(MachineInstr &MI, 
+                                                     MachineBasicBlock *MBB) const {
+  DEBUG_FN_PRINT()
+
+  MI.eraseFromParent();
+  return MBB;
+}
+
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                          SelectCC/SetCC Lowering
+//===----------------------------------------------------------------------===//
+
+MachineBasicBlock *SuperHTargetLowering::insertSELECTCC(MachineInstr &MI, 
+                                                        MachineBasicBlock *MBB) const {
+  DEBUG_FN_PRINT()
+
+  MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
+  const SuperHInstrInfo &TII = *Subtarget->getInstrInfo();
+  MachineBasicBlock::iterator BBI(MI);
+  DebugLoc DL = MI.getDebugLoc();
+
+  MachineOperand TrueV = MI.getOperand(0);
+  MachineOperand FalseV = MI.getOperand(1);
+  ISD::CondCode CC = (ISD::CondCode)MI.getOperand(3).getImm();
+
+  // Lower True-False selection
+  if (TrueV.isImm() && FalseV.isImm()) {
+    if (TrueV.getImm() == 1 && FalseV.getImm() == 0) {
+      BuildMI(*MBB, BBI, DL, TII.get(SH::MOVTRn), SH::R0);
+      MI.eraseFromParent();
+      return MBB;
+    }
+  }
+
+  // To "insert" a SELECT instruction, we insert the diamond
+  // control-flow pattern. The incoming instruction knows the
+  // destination vreg to set, the condition code register to branch
+  // on, the true/false values to select between, and a branch opcode
+  // to use.
+
+  MachineFunction *MF = MBB->getParent();
+  const BasicBlock *LLVM_BB = MBB->getBasicBlock();
+  MachineBasicBlock *FallThrough = MBB->getFallThrough();
+
+  // If the current basic block falls through to another basic block,
+  // we must insert an unconditional branch to the fallthrough destination
+  // if we are to insert basic blocks at the prior fallthrough point.
+  if (FallThrough != nullptr) {
+    BuildMI(MBB, DL, TII.get(SH::BRA)).addMBB(FallThrough);
+  }
+
+  MachineBasicBlock *trueMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+  MachineBasicBlock *falseMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+
+  MachineFunction::iterator I;
+  for (I = MF->begin(); I != MF->end() && &(*I) != MBB; ++I)
+    ;
+  if (I != MF->end())
+    ++I;
+  MF->insert(I, trueMBB);
+  MF->insert(I, falseMBB);
+
+  // Set the call frame size on entry to the new basic blocks.
+  unsigned CallFrameSize = TII.getCallFrameSizeAt(MI);
+  trueMBB->setCallFrameSize(CallFrameSize);
+  falseMBB->setCallFrameSize(CallFrameSize);
+
+  // Transfer remaining instructions and all successors of the current
+  // block to the block which will contain the Phi node for the
+  // select.
+  trueMBB->splice(trueMBB->begin(), MBB,
+                  std::next(MachineBasicBlock::iterator(MI)), MBB->end());
+  trueMBB->transferSuccessorsAndUpdatePHIs(MBB);
+
+  BuildMI(MBB, DL, TII.getBrCond(CC)).addMBB(trueMBB);
+  BuildMI(MBB, DL, TII.get(SH::BRA)).addMBB(falseMBB);
+  MBB->addSuccessor(falseMBB);
+  MBB->addSuccessor(trueMBB);
+
+  // Unconditionally flow back to the true block
+  BuildMI(falseMBB, DL, TII.get(SH::BRA)).addMBB(trueMBB);
+  falseMBB->addSuccessor(trueMBB);
+
+  // Set up the Phi node to determine where we came from
+  BuildMI(*trueMBB, trueMBB->begin(), DL, TII.get(SH::PHI),
+          MI.getOperand(0).getReg())
+      .addReg(MI.getOperand(1).getReg())
+      .addMBB(MBB)
+      .addReg(MI.getOperand(2).getReg())
+      .addMBB(falseMBB);
+
+  MI.eraseFromParent(); // The pseudo instruction is gone now.
+  return trueMBB;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                              CUSTOM LOWERING
+//===----------------------------------------------------------------------===//
+
+MachineBasicBlock *
+SuperHTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
+                                                  MachineBasicBlock *MBB) const {
+  int Op = MI.getOpcode();
+
+  switch (Op) {
+  default: break;
+  case SH::Select8:
+  case SH::Select16:
+  case SH::Select32:
+    return insertSELECTCC(MI, MBB);
+  case SH::LDI8:
+  case SH::LDI16:
+  case SH::LDI32:
+    return insertLoad(MI, MBB);
+  case SH::STI8:
+  case SH::STI16:
+  case SH::STI32:
+    return insertStore(MI, MBB);
+  }
+
+  return MBB;
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index ffdc90b53afc1..6f761b167f98e 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -70,9 +70,20 @@ class SuperHTargetLowering : public TargetLowering  {
   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
-  SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &OutCC,
+  SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
                    SelectionDAG &DAG, SDLoc DL) const;
+
+  // Inserters
+  MachineBasicBlock *
+  EmitInstrWithCustomInserter(MachineInstr &MI,
+                              MachineBasicBlock *MBB) const override;
 private:
+  MachineBasicBlock *insertSELECTCC(MachineInstr &MI, 
+                                    MachineBasicBlock *BB) const;
+  MachineBasicBlock *insertLoad(MachineInstr &MI, 
+                                MachineBasicBlock *BB) const;
+  MachineBasicBlock *insertStore(MachineInstr &MI, 
+                                 MachineBasicBlock *BB) const;
 
   SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override;
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index 1c2e6e03f6b3c..e8624d62397e5 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -74,10 +74,28 @@ class SHInst32<dag outs, dag ins, string asmstr, list<dag> pattern = []>
 // in later passes implemented in C++.
 class SHPseudo<dag outs, dag ins, string asmstr="; error: this should not be emitted", list<dag> pattern = []>
     : SHInst<outs, ins, asmstr, pattern> {
+  let Pattern = pattern;
+
   let isCodeGenOnly = 1;
   let isPseudo = 1;
 }
 
+class SHSelectPseudo<dag outs, dag ins, string asmstr, list<dag> pattern> 
+      : SHPseudo<outs, ins, asmstr, pattern> {
+  let usesCustomInserter = 1;
+  let Uses = [SR];
+}
+
+class SHLoadPseudo<dag outs, dag ins, string asmstr, list<dag> pattern> 
+      : SHPseudo<outs, ins, asmstr, pattern> {
+  let usesCustomInserter = 1;
+}
+
+class SHStorePseudo<dag outs, dag ins, string asmstr, list<dag> pattern> 
+      : SHPseudo<outs, ins, asmstr, pattern> {
+  let usesCustomInserter = 1;
+}
+
 
 
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index e27b09e12fd4f..2b24bd6372234 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -18,11 +18,11 @@
 #include "MCTargetDesc/SuperHInstPrinter.h"
 #include "SuperH.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrInfo.h"
@@ -42,6 +42,8 @@ SuperHInstrInfo::SuperHInstrInfo(const SuperHSubtarget &ST)
     : SuperHGenInstrInfo(ST, RI, SH::ADJCALLSTACKDOWN, SH::ADJCALLSTACKUP),
       RI(ST), Subtarget(ST) { }
 
+// Pin the vtable to this file.
+void SuperHInstrInfo::anchor() {}
 
 
 // Gets whether a given opcode can fill a delay slot.
@@ -99,8 +101,14 @@ const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
   default:
     llvm_unreachable("Unknown condition code!");
   case ISD::SETTRUE:
+  case ISD::SETEQ:
+  case ISD::SETGT:
+  case ISD::SETGE:
     return get(SH::BT);
   case ISD::SETFALSE:
+  case ISD::SETNE:
+  case ISD::SETLT:
+  case ISD::SETLE:
     return get(SH::BF);
   }
 }
@@ -134,6 +142,140 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   llvm_unreachable("Impossible reg-to-reg copy");
 }
 
+void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 
+                                          Register SrcReg, bool isKill, int FrameIndex, 
+                                          const TargetRegisterClass *RC, Register VReg, 
+                                          MachineInstr::MIFlag Flags) const {
+  LLVM_DEBUG(dbgs() << "Store " << RI.getName(SrcReg) << " to slot " << FrameIndex << "\n");
+
+  MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+  const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
+  int64_t Offset = MFI.getObjectOffset(FrameIndex) + 
+                   MFI.getStackSize() - 
+                   TFI->getOffsetOfLocalArea();
+
+  // NOTE:  R0-based displacement instructions have a different encoding
+  //        from Rn based instructions, as such we need to know whether
+  //        we need to copy the src register into R0 temporarily.
+  Register SrcStrReg;
+  unsigned Opcode = 0;
+  if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
+    Opcode = SH::MOVBR0D4Rni;
+    SrcStrReg = SH::R0;
+  } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
+    Opcode = SH::MOVWR0D4Rni;
+    SrcStrReg = SH::R0;
+  } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
+    Opcode = SH::MOVLRmD4Rni;
+    SrcStrReg = SrcReg;
+  } else {
+    llvm_unreachable("Cannot store this register into a stack slot!");
+  }
+
+  // mov r14,r1
+  // add #-<frame size>,r1
+  BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SH::R1)
+    .addReg(SH::R14);
+  BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI8Rn), SH::R1)
+    .addReg(SH::R1)
+    .addImm(-(int)MFI.getStackSize());
+
+  // mov srcreg,r0
+  // mov.b/w r0,@(<offset>,r1)
+  if (SrcStrReg != SrcReg) {
+    BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SrcStrReg)
+      .addReg(SrcReg, getKillRegState(isKill));
+    BuildMI(MBB, MI, DebugLoc(), get(Opcode))
+      .addReg(SH::R1)
+      .addImm(Offset);
+    return;
+  }
+
+  // mov.l srcreg,@(<offset>,r1)
+  BuildMI(MBB, MI, DebugLoc(), get(Opcode))
+      .addReg(SrcReg, getKillRegState(isKill))
+      .addReg(SH::R1)
+      .addImm(Offset);
+}
+
+void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 
+                                           Register DestReg, int FrameIndex, 
+                                           const TargetRegisterClass *RC, Register VReg,
+                                           unsigned SubReg, MachineInstr::MIFlag Flags) const {
+  MachineFunction &MF = *MBB.getParent();
+  const SuperHRegisterInfo &RI = getRegisterInfo();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+  const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
+  int64_t Offset = MFI.getObjectOffset(FrameIndex) + 
+                   MFI.getStackSize() - 
+                   TFI->getOffsetOfLocalArea();
+
+  LLVM_DEBUG(dbgs() << "Load " << RI.getName(DestReg) << " from slot " << FrameIndex << "\n");
+
+  // NOTE:  R0-based displacement instructions have a different encoding
+  //        from Rn based instructions, as such we need to know whether
+  //        we need to copy to our dst register from R0.
+  unsigned Opcode = 0;
+  Register DstStrReg;
+  if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
+    Opcode = SH::MOVBD4RmiR0;
+    DstStrReg = SH::R0;
+  } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
+    Opcode = SH::MOVWD4RmiR0;
+    DstStrReg = SH::R0;
+  } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
+    Opcode = SH::MOVLD4RmiRn;
+    DstStrReg = DestReg;
+  } else {
+    llvm_unreachable("Cannot load this register into a stack slot!");
+  }
+
+  // mov r14,r1
+  // add #-<frame size>,r1
+  BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SH::R1)
+    .addReg(SH::R14);
+  BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI8Rn), SH::R1)
+    .addReg(SH::R1)
+    .addImm(-(int)MFI.getStackSize());
+
+  // mov.b/w @(<offset>,r1),r0
+  // mov r0,dstreg
+  if (DstStrReg != DestReg) {
+    BuildMI(MBB, MI, DebugLoc(), get(Opcode))
+      .addReg(SH::R1)
+      .addImm(Offset);
+    BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), DestReg)
+      .addReg(DstStrReg);
+    return;
+  }
+
+  // mov.l @(<offset>,r1),destreg
+  BuildMI(MBB, MI, DebugLoc(), get(Opcode), DestReg)
+      .addReg(SH::R1)
+      .addImm(Offset);
+}
+
+Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+  if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
+      MI.getOperand(2).getImm() == 0) {
+    FrameIndex = MI.getOperand(1).getIndex();
+    return MI.getOperand(0).getReg();
+  }
+  return 0;
+}
+
+Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+  if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
+      MI.getOperand(1).getImm() == 0) {
+    FrameIndex = MI.getOperand(0).getIndex();
+    return MI.getOperand(2).getReg();
+  }
+  return 0;
+}
+
 
 
 
@@ -226,25 +368,30 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
         continue;
       }
 
-      // Handle subsequent conditional branches. Only handle the case where all
-      // conditional branches branch to the same destination.
-      assert(Cond.size() == 1);
-      assert(TBB);
-
-      // Only handle the case where all conditional branches branch to
-      // the same destination.
-      if (TBB != I->getOperand(0).getMBB()) {
-        return true;
-      }
+      FBB = TBB;
+      TBB = I->getOperand(0).getMBB();
+      Cond.push_back(MachineOperand::CreateImm(BranchCode));
+      continue;
+    }
 
-      ISD::CondCode OldBranchCode = (ISD::CondCode)Cond[0].getImm();
-      // If the conditions are the same, we can leave them alone.
-      if (OldBranchCode == BranchCode) {
-        continue;
-      }
+    // Handle subsequent conditional branches. Only handle the case where all
+    // conditional branches branch to the same destination.
+    assert(Cond.size() == 1);
+    assert(TBB);
 
+    // Only handle the case where all conditional branches branch to
+    // the same destination.
+    if (TBB != I->getOperand(0).getMBB()) {
       return true;
     }
+
+    ISD::CondCode OldBranchCode = (ISD::CondCode)Cond[0].getImm();
+    // If the conditions are the same, we can leave them alone.
+    if (OldBranchCode == BranchCode) {
+      continue;
+    }
+
+    return true;
   }
 
   return false;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index da25ff9390727..2a73b55410f1a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -17,6 +17,7 @@
 #include "SuperHRegisterInfo.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
 
 #define GET_INSTRINFO_HEADER
 #include "SuperHGenInstrInfo.inc"
@@ -26,6 +27,7 @@ namespace llvm {
 class SuperHInstrInfo : public SuperHGenInstrInfo {
   const SuperHRegisterInfo RI;
   const SuperHSubtarget &Subtarget;
+  virtual void anchor();
 
 public:
   explicit SuperHInstrInfo(const SuperHSubtarget &STI);
@@ -59,6 +61,19 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
                            Register DestReg, Register SrcReg, bool KillSrc,
                            bool RenamableDest = false,
                            bool RenamableSrc = false) const override;
+  void storeRegToStackSlot(
+      MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
+      bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
+      MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
+  void loadRegFromStackSlot(
+      MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg,
+      int FrameIndex, const TargetRegisterClass *RC, Register VReg,
+      unsigned SubReg = 0,
+      MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
+  Register isLoadFromStackSlot(const MachineInstr &MI,
+                               int &FrameIndex) const override;
+  Register isStoreToStackSlot(const MachineInstr &MI,
+                              int &FrameIndex) const override;
 
   // Branch Analysis
   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 98b3fd921a5a4..93d03ebcf3aad 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -50,10 +50,10 @@ def SHSDT_CallSeqEnd    : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
 def SHSDT_Call          : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
 def SHSDT_PICAdd        : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
                                           SDTCisPtrTy<1>, SDTCisVT<2, i32>]>;
-def SHSDT_Brcond        : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisInt<1>]>;
-def SHSDT_Cmp           : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisInt<2>]>;
-def SHSDT_SelectCC      : SDTypeProfile<1, 3,
-                          [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisInt<3>]>;
+def SHSDT_Brcond        : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, OtherVT>]>;
+def SHSDT_Cmp           : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, OtherVT>]>;
+def SHSDT_SelectCC      : SDTypeProfile<1, 3, 
+                          [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>;
 
 //===--------------------------------------------------------------------------===//
 // SuperH Specific Nodes
@@ -259,29 +259,29 @@ def MOVRmRn       : InstRmRn<0b0110000000000011,
 let hasSideEffects = 0 in 
 def MOVI8Rn       : InstRnI8<0b1110000000000000,
                             (outs GPR:$Rn), (ins imm8:$imm),
-                            "mov #$imm,$Rn",
-                            [(set i32:$Rn, imm8:$imm)]>;
+                            "mov $imm,$Rn",
+                            [(set i32:$Rn, imm:$imm)]>;
 
 // mova @(disp, PC), R0
 let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
 def MOVAD8PCR0      : InstD8<0b1100011100000000,
-                            (outs), (ins disp8:$disp),
-                            "mova @($disp,PC),R0",
-                            [(set R0, (load disp8:$disp))]>;
+                            (outs), (ins pcrel8:$disp),
+                            "mova $disp,r0",
+                            []>;
 
 // mov.w @(disp,PC), Rn 
 let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
 def MOVWD8PCRn    : InstRnD8<0b1001000000000000,
-                            (outs GPR:$Rn), (ins disp8:$disp),
-                            "mov.w @($disp,PC),$Rn",
-                            [(set i32:$Rn, (sextloadi16 disp8:$disp))]>;
+                            (outs GPR:$Rn), (ins pcrel8:$disp),
+                            "mov.w $disp,$Rn",
+                            [(set i32:$Rn, (sextloadi16 constpool:$disp))]>;
 
 // mov.l @(disp,PC), Rn 
 let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
 def MOVLD8PCRn    : InstRnD8<0b1101000000000000,
-                            (outs GPR:$Rn), (ins disp8:$disp),
-                            "mov.l @($disp,PC),$Rn",
-                            [(set i32:$Rn, (load disp8:$disp))]>;
+                            (outs GPR:$Rn), (ins pcrel8:$disp),
+                            "mov.l $disp,$Rn",
+                            [(set i32:$Rn, (load constpool:$disp))]>;
 
 // movt Rn
 def MOVTRn          : InstRn<0b0000000000101001,
@@ -316,38 +316,41 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
 
   // mov.b @Rm, Rn
   def MOVBRmiRn         : InstRmRn<0b0110000000000000,
-                                  (outs GPR:$Rn), (ins GPR:$Rm),
-                                  "mov.b @$Rm,$Rn",
-                                  [(set i32:$Rn, (sextloadi8 i32:$Rm))]>;
+                                  (outs GPR:$Rn), (ins IGPR:$Rm),
+                                  "mov.b $Rm,$Rn",
+                                  []>;
 
   // mov.w @Rm, Rn
   def MOVWRmiRn         : InstRmRn<0b0110000000000001,
-                                  (outs GPR:$Rn), (ins GPR:$Rm),
-                                  "mov.w @$Rm,$Rn",
-                                  [(set i32:$Rn, (sextloadi16 i32:$Rm))]>;
+                                  (outs GPR:$Rn), (ins IGPR:$Rm),
+                                  "mov.w $Rm,$Rn",
+                                  []>;
 
   // mov.l @Rm, Rn
   def MOVLRmiRn         : InstRmRn<0b0110000000000010,
-                                  (outs GPR:$Rn), (ins GPR:$Rm),
-                                  "mov.l @$Rm,$Rn",
-                                  [(set i32:$Rn, (load i32:$Rm))]>;
+                                  (outs GPR:$Rn), (ins IGPR:$Rm),
+                                  "mov.l $Rm,$Rn",
+                                  []>;
 
   // mov.b @Rm+, Rn
+  let isDelayIllegal = 1 in
   def MOVBRminciRn      : InstRmRn<0b0110000000000100,
-                                  (outs GPR:$Rn), (ins GPR:$Rm),
-                                  "mov.b @$Rm+,$Rn",
+                                  (outs GPR:$Rn), (ins IGPRInc:$Rm),
+                                  "mov.b $Rm,$Rn",
                                   []>;
 
   // mov.w @Rm+, Rn
+  let isDelayIllegal = 1 in
   def MOVWRminciRn      : InstRmRn<0b0110000000000101,
-                                  (outs GPR:$Rn), (ins GPR:$Rm),
-                                  "mov.w @$Rm+,$Rn",
+                                  (outs GPR:$Rn), (ins IGPRInc:$Rm),
+                                  "mov.w $Rm,$Rn",
                                   []>;
 
   // mov.l @Rm+, Rn
+  let isDelayIllegal = 1 in
   def MOVLRminciRn      : InstRmRn<0b0110000000000110,
-                                  (outs GPR:$Rn), (ins GPR:$Rm),
-                                  "mov.l @$Rm+,$Rn",
+                                  (outs GPR:$Rn), (ins IGPRInc:$Rm),
+                                  "mov.l $Rm,$Rn",
                                   []>;
 
   // mov.b @(disp, Rm), R0
@@ -366,7 +369,7 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
   
   // mov.l @(disp, Rm), Rn
   def MOVLD4RmiRn     : InstRmRnD4<0b0101000000000000,
-                                  (outs GPRMem:$Rn), (ins GPR:$Rm, disp4:$disp),
+                                  (outs GPR:$Rn), (ins GPR:$Rm, disp4:$disp),
                                   "mov.l @($disp,$Rm),$Rn",
                                   []>;
 
@@ -424,57 +427,60 @@ let hasSideEffects = 0, mayStore = 1 in {
 
   // mov.b Rm, @Rn
   def MOVBRmRni         : InstRmRn<0b0010000000000000,
-                                  (outs), (ins GPRMem:$Rn, GPR:$Rm),
-                                  "mov.b $Rm,@$Rn",
-                                  [(truncstorei8 i32:$Rm, GPRMem:$Rn)]>;
+                                  (outs), (ins GPR:$Rm, IGPR:$Rn),
+                                  "mov.b $Rm,$Rn",
+                                  []>;
 
   // mov.w Rm, @Rn
   def MOVWRmRni         : InstRmRn<0b0010000000000001,
-                                  (outs), (ins GPR:$Rm, GPRMem:$Rn),
-                                  "mov.w $Rm,@$Rn",
-                                  [(truncstorei16 i32:$Rm, GPRMem:$Rn)]>;
+                                  (outs), (ins GPR:$Rm, IGPR:$Rn),
+                                  "mov.w $Rm,$Rn",
+                                  []>;
 
   // mov.l Rm, @Rn
   def MOVLRmRni         : InstRmRn<0b0010000000000010,
-                                  (outs), (ins GPRMem:$Rn, GPR:$Rm),
-                                  "mov.l $Rm,@$Rn",
-                                  [(store i32:$Rm, GPRMem:$Rn)]>;
+                                  (outs), (ins GPR:$Rm, IGPR:$Rn),
+                                  "mov.l $Rm,$Rn",
+                                  []>;
 
   // mov.b Rm, @-Rn
+  let isDelayIllegal = 1 in
   def MOVBRmRndeci      : InstRmRn<0b0010000000000100,
-                                  (outs), (ins GPRMem:$Rn, GPR:$Rm),
-                                  "mov.b $Rm, at -$Rn",
+                                  (outs), (ins GPR:$Rm, IGPRDec:$Rn),
+                                  "mov.b $Rm,$Rn",
                                   []>;
 
   // mov.w Rm, @-Rn
+  let isDelayIllegal = 1 in
   def MOVWRmRndeci      : InstRmRn<0b0010000000000101,
-                                  (outs), (ins GPR:$Rm, GPRMem:$Rn),
-                                  "mov.w $Rm, at -$Rn",
+                                  (outs), (ins GPR:$Rm, IGPRDec:$Rn),
+                                  "mov.w $Rm,$Rn",
                                   []>;
 
   // mov.l Rm, @-Rn
+  let isDelayIllegal = 1 in
   def MOVLRmRndeci      : InstRmRn<0b0010000000000110,
-                                  (outs), (ins GPRMem:$Rn, GPR:$Rm),
-                                  "mov.l $Rm, at -$Rn",
+                                  (outs), (ins GPR:$Rm, IGPRDec:$Rn),
+                                  "mov.l $Rm,$Rn",
                                   []>;
   
   // mov.b R0, @(disp, Rn)
   let Uses = [R0] in
   def MOVBR0D4Rni       : InstRnD4<0b1000000000000000,
-                                  (outs GPR:$Rn), (ins disp4:$disp),
+                                  (outs), (ins GPR:$Rn, disp4:$disp),
                                   "mov.b R0,@($disp,$Rn)",
                                   []>;
   
   // mov.w R0, @(disp, Rn)
   let Uses = [R0] in
   def MOVWR0D4Rni       : InstRnD4<0b1000000100000000,
-                                  (outs GPR:$Rn), (ins disp4:$disp),
+                                  (outs), (ins GPR:$Rn, disp4:$disp),
                                   "mov.w R0,@($disp,$Rn)",
                                   []>;
   
   // mov.l Rm, @(disp, Rn)
   def MOVLRmD4Rni     : InstRmRnD4<0b0001000000000000,
-                                  (outs GPR:$Rn), (ins GPR:$Rm, disp4:$disp),
+                                  (outs), (ins GPR:$Rn, GPR:$Rm, disp4:$disp),
                                   "mov.l $Rm,@($disp,$Rn)",
                                   []>;
 
@@ -547,7 +553,7 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
   // add imm:8, Rn
   def ADDI8Rn       : InstRnI8<0b0111000000000000, 
                               (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
-                              "add #$imm,$Rn",
+                              "add $imm,$Rn",
                               [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
 
   // addc Rm, Rn
@@ -627,20 +633,54 @@ let hasSideEffects = 0 in {
 
 let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 
+  // mac.w @Rm+, @Rn+
+  let Defs = [MACL] in
+  def MACWRmRn      : InstRmRn<0b0100000000001111, 
+                              (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
+                              "mac.w $Rm,$Rn",
+                              []>;
+
+  // mac.l @Rm+, @Rn+
+  let Defs = [MACL, MACH] in
+  def MACLRmRn      : InstRmRn<0b0000000000001111, 
+                              (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
+                              "mac.l $Rm,$Rn",
+                              []>;
+
   // mul.l Rm, Rn
   let Defs = [MACL] in
-  def MULRmRn       : InstRmRn<0b0000000000000111, 
+  def MULLRmRn      : InstRmRn<0b0000000000000111, 
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "mul.l $Rm,$Rn",
                               []>;
 
-  // mulr Rm, Rn
-  let Uses = [R0] in
-  def MULRR0Rn        : InstRn<0b0100000010000000, 
-                              (outs GPR:$Rn), (ins GPR:$src),
-                              "mulr R0,$Rn",
+  // muls.w Rm, Rn
+  let Defs = [MACL] in
+  def MULSWRmRn     : InstRmRn<0b0010000000001111, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "muls.w $Rm,$Rn",
                               []>;
 
+  // mulu.w Rm, Rn
+  let Defs = [MACL] in
+  def MULUWRmRn     : InstRmRn<0b0010000000001110, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "mulu.w $Rm,$Rn",
+                              []>;
+
+  // dmuls.l Rm, Rn
+  let Defs = [MACL, MACH] in
+  def DMULSLRmRn    : InstRmRn<0b0011000000001101, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "dmuls.l $Rm,$Rn",
+                              []>;
+
+  // dmulu.l Rm, Rn
+  let Defs = [MACL, MACH] in
+  def DMULULRmRn    : InstRmRn<0b0011000000000101, 
+                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              "dmulu.l $Rm,$Rn",
+                              []>;
 }
 
 
@@ -797,7 +837,7 @@ def ANDRmRn       : InstRmRn<0b0010000000001001,
 let Defs = [R0], Uses = [R0] in
 def ANDI8R0         : InstI8<0b1100100100000000, 
                             (outs), (ins imm8:$imm),
-                            "and #$imm,R0",
+                            "and $imm,R0",
                             []>;
 
 // not Rm,Rn
@@ -816,7 +856,7 @@ def ORRmRn        : InstRmRn<0b0010000000001011,
 let Defs = [R0], Uses = [R0] in
 def ORI8R0          : InstI8<0b1100101100000000, 
                             (outs), (ins imm8:$imm),
-                            "or #$imm,R0",
+                            "or $imm,R0",
                             []>;
 
 // xor Rm,Rn
@@ -829,7 +869,7 @@ def XORRmRn       : InstRmRn<0b0010000000001010,
 let Defs = [R0], Uses = [R0] in
 def XORI8R0         : InstI8<0b1100101000000000, 
                             (outs), (ins imm8:$imm),
-                            "xor #$imm,R0",
+                            "xor $imm,R0",
                             []>;
 
 // tst Rm,Rn
@@ -842,7 +882,7 @@ def TSTRmRn       : InstRmRn<0b0010000000001000,
 let Defs = [SR], Uses = [R0] in
 def TSTI8R0         : InstI8<0b1100100000000000, 
                             (outs), (ins imm8:$imm),
-                            "tst #$imm,R0",
+                            "tst $imm,R0",
                             []>;
 
 
@@ -1010,8 +1050,8 @@ let isTerminator = 1 in {
 
   let isBranch = 1, isBarrier = 1, hasDelaySlot = 1 in
   def JMP             : InstRm<0b0100000000101011, 
-                              (outs), (ins GPR:$Rm),
-                              "jmp @$Rm",
+                              (outs), (ins IGPR:$Rm),
+                              "jmp $Rm",
                               []>;
 }
 
@@ -1024,9 +1064,9 @@ let isTerminator = 1 in {
 let isCall = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in {
   let Uses = [SR, GBR] in
   def JSRRmi          : InstRm<0b0100000000001011,
-                              (outs), (ins GPRMem:$Rm),
-                              "jsr @$Rm",
-                              [(SHCall GPRMem:$Rm)]>;
+                              (outs), (ins IGPR:$Rm),
+                              "jsr $Rm",
+                              [(SHCall IGPR:$Rm)]>;
 }
 
 
@@ -1071,8 +1111,8 @@ def LDCRmSR           : InstRm<0b0100000000001110,
 // ldc.l @Rm+, SR
 let Defs = [SR], isDelayIllegal = 1 in
 def LDCLRminciSR      : InstRm<0b0100000000000111, 
-                              (outs), (ins GPR:$Rm), 
-                              "ldc.l @$Rm+,SR",
+                              (outs), (ins IGPRInc:$Rm), 
+                              "ldc.l $Rm,SR",
                               []>;
 
 // ldc Rm, GBR
@@ -1085,8 +1125,8 @@ def LDCRmGBR          : InstRm<0b0100000000011110,
 // ldc.l @Rm+, GBR
 let Defs = [GBR] in
 def LDCLRminciGBR     : InstRm<0b0100000000010111, 
-                              (outs), (ins GPR:$Rm), 
-                              "ldc.l @$Rm+,GBR",
+                              (outs), (ins IGPRInc:$Rm), 
+                              "ldc.l $Rm,GBR",
                               []>;
 
 // ldc Rm, VBR
@@ -1099,8 +1139,8 @@ def LDCRmVBR          : InstRm<0b0100000000101110,
 // ldc.l @Rm+, VBR
 let Defs = [VBR], isDelayIllegal = 1 in
 def LDCLRminciVBR     : InstRm<0b0100000000100111, 
-                              (outs), (ins GPR:$Rm), 
-                              "ldc.l @$Rm+,VBR",
+                              (outs), (ins IGPRInc:$Rm), 
+                              "ldc.l $Rm,VBR",
                               []>;
 
 // lds Rm, MACH
@@ -1113,8 +1153,8 @@ def LDSRmMACH         : InstRm<0b0100000000001010,
 // lds.l @Rm+, MACH
 let Defs = [MACH] in
 def LDSLRminciMACH    : InstRm<0b0100000000000110, 
-                              (outs), (ins GPR:$Rm), 
-                              "lds.l @$Rm+,MACH",
+                              (outs), (ins IGPRInc:$Rm), 
+                              "lds.l $Rm,MACH",
                               []>;
 
 // lds Rm, MACL
@@ -1127,8 +1167,8 @@ def LDSRmMACL         : InstRm<0b0100000000011010,
 // lds.l @Rm+, MACL
 let Defs = [MACH] in
 def LDSLRminciMACL    : InstRm<0b0100000000010110, 
-                              (outs), (ins GPR:$Rm), 
-                              "lds.l @$Rm+,MACL",
+                              (outs), (ins IGPRInc:$Rm), 
+                              "lds.l $Rm,MACL",
                               []>;
 
 // lds Rm, PR
@@ -1141,8 +1181,8 @@ def LDSRmPR           : InstRm<0b0100000000101010,
 // lds.l @Rm+, PR
 let Defs = [PR] in
 def LDSLRminciPR      : InstRm<0b0100000000100110, 
-                              (outs), (ins GPR:$Rm), 
-                              "lds.l @$Rm+,PR",
+                              (outs), (ins IGPRInc:$Rm), 
+                              "lds.l $Rm,PR",
                               []>;
 
 // nop
@@ -1171,8 +1211,8 @@ def STCSRRn           : InstRn<0b0000000000000010,
 // stc.l SR, at -Rn
 let Uses = [SR], isDelayIllegal = 1 in
 def STCLSRRndeci      : InstRn<0b0100000000000011, 
-                              (outs GPR:$Rn), (ins), 
-                              "stc.l SR, at -$Rn",
+                              (outs IGPRDec:$Rn), (ins), 
+                              "stc.l SR,$Rn",
                               []>;
 
 // stc GBR,Rn
@@ -1185,8 +1225,8 @@ def STCGBRRn          : InstRn<0b0000000000010010,
 // stc.l GBR, at -Rn
 let Uses = [GBR] in
 def STCLGBRRndeci     : InstRn<0b0100000000010011, 
-                              (outs GPR:$Rn), (ins), 
-                              "stc.l GBR, at -$Rn",
+                              (outs IGPRDec:$Rn), (ins), 
+                              "stc.l GBR,$Rn",
                               []>;
 
 // stc VBR,Rn
@@ -1199,8 +1239,8 @@ def STCVBRRn          : InstRn<0b0000000000100010,
 // stc.l VBR, at -Rn
 let Uses = [VBR], isDelayIllegal = 1 in
 def STCLVBRRndeci     : InstRn<0b0100000000100011, 
-                              (outs GPR:$Rn), (ins), 
-                              "stc.l VBR, at -$Rn",
+                              (outs IGPRDec:$Rn), (ins), 
+                              "stc.l VBR,$Rn",
                               []>;
 
 // sts MACH,Rn
@@ -1213,8 +1253,8 @@ def STSMACHRn         : InstRn<0b0000000000001010,
 // sts.l MACH, at -Rn
 let Uses = [MACH] in
 def STSLMACHRndeci    : InstRn<0b0100000000000010, 
-                              (outs GPR:$Rn), (ins), 
-                              "sts.l MACH, at -$Rn",
+                              (outs IGPRDec:$Rn), (ins), 
+                              "sts.l MACH,$Rn",
                               []>;
 
 // sts MACL,Rn
@@ -1227,8 +1267,8 @@ def STSMACLRn         : InstRn<0b0000000000011010,
 // sts.l MACL, at -Rn
 let Uses = [MACL] in
 def STSLMACLRndeci    : InstRn<0b0100000000010010, 
-                              (outs GPR:$Rn), (ins), 
-                              "sts.l MACL, at -$Rn",
+                              (outs IGPRDec:$Rn), (ins), 
+                              "sts.l MACL,$Rn",
                               []>;
 
 // sts PR,Rn
@@ -1241,15 +1281,15 @@ def STSPRRn           : InstRn<0b0000000000101010,
 // sts.l PR, at -Rn
 let Uses = [PR] in
 def STSLPRRndeci      : InstRn<0b0100000000100010, 
-                              (outs GPR:$Rn), (ins), 
-                              "sts.l PR, at -$Rn",
+                              (outs IGPRDec:$Rn), (ins), 
+                              "sts.l PR,$Rn",
                               []>;
 
 // trapa #imm
 let Defs = [PC], isCall = 1 in
 def TRAPAI8           : InstI8<0b1100001100000000, 
                               (outs), (ins imm8:$imm), 
-                              "trapa #$imm",
+                              "trapa $imm",
                               []>;
 
 
@@ -1277,13 +1317,26 @@ include "SuperHInstrDSP.td"
 // Zero-Extend Load
 //===--------------------------------------------------------------------------===//
 
-def : Pat<(i32 (zextloadi1 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
-def : Pat<(i32 (zextloadi8 i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
-def : Pat<(i32 (zextloadi16 i32:$src)), (EXTUWRmRn (MOVWRmiRn i32:$src))>;
-def : Pat<(i32 (extloadi1 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
-def : Pat<(i32 (extloadi8 i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
-def : Pat<(i32 (extloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
+// def : Pat<(i32 (zextloadi1  i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (zextloadi8  i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (zextloadi16 i32:$src)), (EXTUWRmRn (MOVWRmiRn i32:$src))>;
+// def : Pat<(i32 (extloadi1   i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (extloadi8   i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (extloadi16  i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
+// def : Pat<(i32 (sextloadi1  i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (sextloadi8  i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
+// def : Pat<(i32 (sextloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
+// 
+// def : Pat<(sext_inreg i32:$src, i1),  (EXTSBRmRn i32:$src)>;
+// def : Pat<(sext_inreg i32:$src, i8),  (EXTSBRmRn i32:$src)>;
+// def : Pat<(sext_inreg i32:$src, i16), (EXTSWRmRn i32:$src)>;
+
+//===--------------------------------------------------------------------------===//
+// Truncating Store
+//===--------------------------------------------------------------------------===//
 
+// def : Pat<(truncstorei8  i32:$src, i32:$dst), (MOVBRmRni i32:$src, i32:$dst)>;
+// def : Pat<(truncstorei16 i32:$src, i32:$dst), (MOVWRmRni i32:$src, i32:$dst)>;
 
 
 
@@ -1293,6 +1346,62 @@ def : Pat<(i32 (extloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
+//===--------------------------------------------------------------------------===//
+// Loads & Stores
+//===--------------------------------------------------------------------------===//
+
+def LDI8          : SHLoadPseudo<(outs GPR:$dst),
+                                (ins IGPR:$src),
+                                "; LDI8 PSEUDO",
+                                [(set i32:$dst, (sextloadi8 addr:$src))]>;
+
+def LDI16         : SHLoadPseudo<(outs GPR:$dst),
+                                (ins IGPR:$src),
+                                "; LDI16 PSEUDO",
+                                [(set i32:$dst, (sextloadi16 addr:$src))]>;
+
+def LDI32         : SHLoadPseudo<(outs GPR:$dst),
+                                (ins IGPR:$src),
+                                "; LDI32 PSEUDO",
+                                [(set i32:$dst, (load addr:$src))]>;
+
+def STI8         : SHStorePseudo<(outs),
+                                (ins GPR:$src, IGPR:$dst),
+                                "; STI8 PSEUDO",
+                                [(truncstorei8 i32:$src, addr:$dst)]>;
+
+def STI16        : SHStorePseudo<(outs),
+                                (ins GPR:$src, IGPR:$dst),
+                                "; STI16 PSEUDO",
+                                [(truncstorei16 i32:$src, addr:$dst)]>;
+
+def STI32        : SHStorePseudo<(outs),
+                                (ins GPR:$src, IGPR:$dst),
+                                "; STI32 PSEUDO",
+                                [(store i32:$src, addr:$dst)]>;
+
+//===--------------------------------------------------------------------------===//
+// SelectCC & SetCC
+//===--------------------------------------------------------------------------===//
+
+def Select8     : SHSelectPseudo<(outs GPR:$dst),
+                                (ins GPR:$src, GPR:$src2, i8imm:$cc),
+                                "; Select8 PSEUDO",
+                                [(set i8:$dst,
+                                 (SHselectcc i8:$src, i8:$src2, imm:$cc))]>;
+
+def Select16    : SHSelectPseudo<(outs GPR:$dst),
+                                (ins GPR:$src, GPR:$src2, i8imm:$cc),
+                                "; Select16 PSEUDO",
+                                [(set i16:$dst,
+                                 (SHselectcc i16:$src, i16:$src2, imm:$cc))]>;
+
+def Select32    : SHSelectPseudo<(outs GPR:$dst),
+                                (ins GPR:$src, GPR:$src2, i8imm:$cc),
+                                "; Select32 PSEUDO",
+                                [(set i32:$dst,
+                                 (SHselectcc i32:$src, i32:$src2, imm:$cc))]>;
+
 //===--------------------------------------------------------------------------===//
 // Stack Frame
 //===--------------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index d5b7cc883b51f..157e06680e986 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -23,7 +23,7 @@ SuperHMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
   const MCExpr *Expr = nullptr;
   switch (MO.getTargetFlags()) {
     case SHII::MO_NO_FLAG:
-      Expr = MCSymbolRefExpr::create(Sym, SH::S_None, Ctx);
+      Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
       break;
 
     case SHII::MO_GOT:
@@ -79,11 +79,6 @@ void SuperHMCInstLower::lowerInstruction(const MachineInstr &MI,
           MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()), Subtarget);
       break;
     case MachineOperand::MO_MachineBasicBlock:
-
-      // NOTE:  Branch instructions will generally jump to labels.
-      //        so ensure we emit them if they're referenced in an
-      //        operand during lowering.
-      MO.getMBB()->setLabelMustBeEmitted();
       MCOp = MCOperand::createExpr(
           MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
       break;
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
index 880835ebafc49..139e969eb1548 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -47,7 +47,7 @@ SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
       }
     }
   }
-
+  
   // If not found, create a new one and add it.
   MachineFunction &MF = DAG.getMachineFunction();
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
@@ -120,7 +120,7 @@ SuperHConstantPoolSymbol *SuperHMachineFunctionInfo::tryGetConstant(
   unsigned LabelIndex = SFI->createConstIndex();
   return SuperHConstantPoolSymbol::Create(
     *DAG.getContext(), 
-    N->getSymbol(), 
+    N->getSymbol(),
     LabelIndex
   );
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 6c40c0f25fdd0..1c7ea011a5ed2 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -60,6 +60,10 @@ SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
     return &SH::GPRRegClass;
   }
 
+  if (TRI->isTypeLegalForClass(*RC, MVT::i1)) {
+    return &SH::GPRRegClass;
+  }
+
   return TargetRegisterInfo::getLargestLegalSuperClass(RC, MF);
 }
 
@@ -75,6 +79,9 @@ BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   // Also reserve the stack frame and stack pointer.
   Reserved.set(SH::R14);
   Reserved.set(SH::R15);
+
+  // Status Register
+  Reserved.set(SH::SR);
   return Reserved;
 }
 
@@ -88,23 +95,37 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
+  const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
   const TargetInstrInfo &TII = *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
 
-  // NOTE: Stack grows down, so flip this.
-  int Offset = -MFI.getObjectOffset(FrameIndex);
+  int64_t Size = MFI.getObjectSize(FrameIndex);
+  int64_t StackSize = MFI.getStackSize() + 8;
+  int64_t Offset = MFI.getObjectOffset(FrameIndex);
+  
+  // Add 4 to offset because SP points to saved FP
+  Offset += StackSize - TFI->getOffsetOfLocalArea() + 4;
 
-  if (MI.getOpcode() == SH::SHFrmIdx) {
+  // Fold incoming offset.
+  Offset += MI.getOperand(FIOperandNum + 1).getImm();
 
-    // TODO: Lower frames that can't be expressed in 4 bits.
+  if (MI.getOpcode() == SH::SHFrmIdx) {
     Register DstReg = MI.getOperand(0).getReg();
-    MachineInstr *New = BuildMI(MBB, MI, dl, TII.get(SH::MOVLD4RmiRn), DstReg)
-                        .addReg(SH::R14)
-                        .addImm(Offset);
 
+    // mov r14,r1
+    // add #-<frame size>,r1
+    BuildMI(MBB, MI, DebugLoc(), TII.get(SH::MOVRmRn), DstReg)
+      .addReg(SH::R14);
+    BuildMI(MBB, MI, DebugLoc(), TII.get(SH::ADDI8Rn), DstReg)
+      .addReg(DstReg)
+      .addImm(-StackSize);
+
+    II++;
     MI.eraseFromParent();
-    return false;
   }
+
+  MI.getOperand(FIOperandNum).ChangeToRegister(SH::R1, false);
+  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
   return false;
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index f826f06f14337..f44b472825f4c 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -18,6 +18,10 @@
 //===----------------------------------------------------------------------===//
 
 let Namespace = "SH" in {
+  def sub_8      : SubRegIndex<8>;
+  def sub_16     : SubRegIndex<16>;
+  def sub_32     : SubRegIndex<32>;
+
   def sub_64_lo  : SubRegIndex<64>;
   def sub_64_hi  : SubRegIndex<64, 64>;
   def sub_32_lo  : SubRegIndex<32>;
@@ -43,11 +47,40 @@ class SHReg<bits<16> Enc, string n> : Register<n> {
 }
 
 class SHRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs>
-  : RegisterWithSubRegs<n, subregs> {
+    : RegisterWithSubRegs<n, subregs> {
   let HWEncoding = Enc;
   let Namespace = "SH";
 }
 
+// Broken due to issue #218854, resume work on this after it's fixed.
+// // Artificial subregisters of the GPR registers.
+// class GPRReg8<bits<16> Enc, string n>
+//     : SHReg<Enc, n # ".b"> {
+//   let isArtificial = 1;
+// }
+// 
+// class GPRReg16<bits<16> Enc, string n, list<Register> subregs> 
+//     : SHRegWithSubRegs<Enc, n # ".w", subregs> {
+//   let isArtificial = 1;
+//   let SubRegIndices = [sub_8];
+// }
+// 
+// // SH General Purpose Registers.
+// class GPRReg32<bits<16> Enc, string n, list<Register> subregs> 
+//     : SHRegWithSubRegs<Enc, n, subregs> {
+//   let SubRegIndices = [sub_16];
+// }
+// 
+// multiclass GPRReg<bits<16> Enc, string n> {
+//   def NAME#B : GPRReg8<Enc, n>;
+//   defvar RB = !cast<Register>(NAME#B);
+// 
+//   def NAME#W : GPRReg16<Enc, n, [RB]>;
+//   defvar RW = !cast<Register>(NAME#W);
+// 
+//   def NAME   : GPRReg32<Enc, n, [RW]>;
+// }
+
 // SH General Purpose Registers.
 class GPRReg<bits<16> Enc, string n> : SHReg<Enc, n>;
 
@@ -151,7 +184,10 @@ let Namespace = "SH" in {
 // Register Classes
 //===----------------------------------------------------------------------===//
 
-def GPR : RegisterClass<"SH", [ i8, i16, i32 ], 32, (sequence "R%u", 0, 15)>;
+def GPR8  : RegisterClass<"SH", [ i8 ], 32, (sequence "R%u", 0, 15)>;
+def GPR16 : RegisterClass<"SH", [ i16 ], 32, (sequence "R%u", 0, 15)>;
+def GPR32 : RegisterClass<"SH", [ i32 ], 32, (sequence "R%u", 0, 15)>;
+def GPR   : RegisterClass<"SH", [ i8, i16, i32 ], 32, (sequence "R%u", 0, 15)>;
 
 // 32-bit floating point registers.
 def FR32 : RegisterClass<"SH", [ f32 ], 32, (add

>From bf01951dd89b6791cb9e4b09ebc65f70e6863b68 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 3 Sep 2026 12:59:26 +0200
Subject: [PATCH 34/67] Refactor instruction names

---
 .../SuperH/MCTargetDesc/SuperHAsmBackend.cpp  |   5 +
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |   6 +
 .../SuperH/MCTargetDesc/SuperHInstPrinter.h   |   1 +
 .../MCTargetDesc/SuperHMCCodeEmitter.cpp      |  39 ++
 .../Target/SuperH/SuperHFillDelaySlots.cpp    |   2 +-
 .../lib/Target/SuperH/SuperHFrameLowering.cpp |  38 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  24 +-
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 113 +++--
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |   3 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  26 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 422 +++++++++---------
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp |   4 +-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.td  |   6 +-
 13 files changed, 390 insertions(+), 299 deletions(-)

diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 878d658f9e7f3..71bdeb58cb7b3 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -147,6 +147,11 @@ unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixu
   default:
     return Value;
 
+  case FK_Data_2:
+  case FK_Data_4:
+    // NOTE:  Largest possible displacement is 12 bit, so force this.
+    return (Value & 0xFFF);
+
   case SH::fixup_got_low16:
     return (Value+Addend) & 65535;
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 22fc26b77b3e7..1a6148b27ca70 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -45,6 +45,12 @@ void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
   OS << getRegName(Reg);
 }
 
+void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+  const MCOperand &Op0 = MI->getOperand(OpNo);
+  const MCOperand &Op1 = MI->getOperand(OpNo+1);
+  OS << "@(" << Op1.getImm() << "," << getRegName(Op0.getReg()) << ")";
+}
+
 void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
   OS << Op.getImm();
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index 17af288324675..328c42c366b24 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -53,6 +53,7 @@ class SuperHInstPrinter : public MCInstPrinter {
 
   void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
   void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 8d6c613eef9bf..690515d648564 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -32,6 +32,7 @@
 #include "llvm/Support/EndianStream.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <cstdint>
+#include <optional>
 
 
 using namespace llvm;
@@ -120,6 +121,44 @@ unsigned SuperHMCCodeEmitter::getOpBits(const MCInst &MI,
   return getBinaryCodeForInstr(Inst, Fixups, STI);
 }
 
+// @getFixupForOpcode - Helper that gets the neccesary fixup for 
+// the given opcode.
+// This is neccesary due to the various opcodes that access memory
+// have different scaling factors applied.
+static std::optional<MCFixup> getFixupForOpcode(unsigned Opcode, const MCExpr *Expr, MCContext &Ctx) {
+  bool isOp32 = isOpcode32(Opcode) ? FK_Data_4 : FK_Data_2;
+
+  switch(Opcode) {
+  default: break;
+
+  // disp * 2
+  case SH::BF:
+  case SH::BFS:
+  case SH::BT:
+  case SH::BTS:
+  case SH::BSR:
+  case SH::BRA:
+  case SH::MOVWI:
+  case SH::MOVWL4:
+  case SH::MOVWLG:
+  case SH::MOVWS4:
+  case SH::MOVWSG:
+    Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(2, Ctx), Ctx);
+    break;
+
+  // disp * 4
+  case SH::MOVA:
+  case SH::MOVLI:
+  case SH::MOVLL4:
+  case SH::MOVLLG:
+  case SH::MOVLS4:
+  case SH::MOVLSG:
+    Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(4, Ctx), Ctx);
+    break;
+  }
+  return MCFixup::create(0, Expr, isOp32 ? FK_Data_4 : FK_Data_2, true);
+}
+
 void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
                                            SmallVectorImpl<char> &CB,
                                            SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 10510a3e13183..d3f950bfb7477 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -85,7 +85,7 @@ MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI)
     if (MI.isReturn()) {
       
       // Skip the LDS instruction.
-      if (Opcode == SH::LDSLRminciPR || Opcode == SH::LDSRmPR)
+      if (Opcode == SH::LDSPR || Opcode == SH::LDSMPR)
         return nullptr;
     }
 
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index e4341a2d59db7..5b3bd8840f0c7 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -67,7 +67,7 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
 
       // Fast path, emit a single immediate add.
       //    Emit add #-(size),r15
-      BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), SP)
+      BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI), SP)
         .addReg(SP)
         .addImm((int)AdjValue);
       return true;
@@ -77,7 +77,7 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
 
       // Fast path, emit a single immediate add.
       //    Emit add #(size),r14
-      BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI8Rn), FP)
+      BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI), FP)
         .addReg(FP)
         .addImm((int)AdjValue);
       return true;
@@ -89,7 +89,7 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
   unsigned ToShift = getShiftAmt(AdjValue);
 
   // Empty R0 in case it had something.
-  BuildMI(MBB, MBBI, dl, TII.get(SH::MOVI8Rn), SH::R0)
+  BuildMI(MBB, MBBI, dl, TII.get(SH::MOVI), SH::R0)
     .addImm(0)
     .addReg(SH::R0)
     .setMIFlag(MFlag);
@@ -98,10 +98,10 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
   //  or #(byte), r0
   //  shll8 r0
   for(unsigned i = 0; i < ToShift; i++) {
-    BuildMI(MBB, MBBI, dl, TII.get(SH::ORI8R0))
+    BuildMI(MBB, MBBI, dl, TII.get(SH::ORI))
       .addImm((AdjValue >> (i*8)) & 0xFF)
       .setMIFlag(MFlag);
-    BuildMI(MBB, MBBI, dl, TII.get(SH::SHLL8Rn), SH::R0)
+    BuildMI(MBB, MBBI, dl, TII.get(SH::SHLL8), SH::R0)
       .addReg(SH::R0)
       .setMIFlag(MFlag);
   }
@@ -110,12 +110,12 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
   //  neg r0, r0 (if negative displacement)
   //  add r0, r15
   if (AdjValue < 0)
-    BuildMI(MBB, MBBI, dl, TII.get(SH::NEGRmRn), SH::R0)
+    BuildMI(MBB, MBBI, dl, TII.get(SH::NEG), SH::R0)
       .addReg(SH::R0)
       .addReg(SH::R0)
       .setMIFlag(MFlag);
 
-  BuildMI(MBB, MBBI, dl, TII.get(SH::SUBRmRn), SP)
+  BuildMI(MBB, MBBI, dl, TII.get(SH::SUB), SP)
     .addReg(SH::R0, RegState::Kill)
     .addReg(SP)
     .setMIFlag(MFlag);
@@ -149,7 +149,7 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
   // Store GOT
   if (STI.isPositionIndependent()) {
     if (auto *GOTSym = MF.getPICBaseSymbol()) {
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
         .addReg(GOT)
         .setMIFlag(MachineInstr::FrameSetup);
     }
@@ -159,17 +159,17 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
   //    mov.l r14, at -r15
   //    add <stackadj>,r15
   //    mov r15,r14
-  BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRmRndeci), SP)
+  BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
     .addReg(FP)
     .setMIFlag(MachineInstr::FrameSetup);
   emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
-  BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+  BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
     .addReg(SP)
     .setMIFlag(MachineInstr::FrameSetup);
 
   // Save return address to stack.
   if (MFI.hasCalls()) {
-    BuildMI(MBB, MBBI, DL, TII.get(SH::STSLPRRndeci))
+    BuildMI(MBB, MBBI, DL, TII.get(SH::STSMPR))
       .addReg(SP)
       .setMIFlag(MachineInstr::FrameSetup);
   }
@@ -199,7 +199,7 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
 
     // 1. Restore return address from stack.
     if (MFI.hasCalls()) {
-      BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+      BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
         .addReg(SP)
         .setMIFlag(MachineInstr::FrameDestroy);
     }
@@ -207,10 +207,10 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
     // 2. Delete stack frame, restoring stack pointer.
     if (StackSize > 0) {
       emitSPAdj(MF, MBB, MBBI, StackSize);
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
         .addReg(SP)
         .setMIFlag(MachineInstr::FrameDestroy);
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRminciRn), SP)
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
         .addReg(FP)
         .setMIFlag(MachineInstr::FrameDestroy);
     }
@@ -219,7 +219,7 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
 
     // 1. Restore return address from stack.
     if (MFI.hasCalls()) {
-      BuildMI(MBB, MBBI, DL, TII.get(SH::LDSLRminciPR))
+      BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
         .addReg(SP)
         .setMIFlag(MachineInstr::FrameDestroy);
     }
@@ -230,10 +230,10 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
     //    mov.l @r15+,r14
     if (StackSize > 0) {
       emitSPAdj(MF, MBB, MBBI, StackSize);
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVRmRn), FP)
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
         .addReg(SP)
         .setMIFlag(MachineInstr::FrameDestroy);
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLRminciRn), SP)
+      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
         .addReg(FP)
         .setMIFlag(MachineInstr::FrameDestroy);
     }
@@ -256,7 +256,7 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
 
   for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
     MCRegister Reg = I.getReg();
-    BuildMI(MBB, MI, DL, TII.get(SH::MOVLRmRndeci), SP)
+    BuildMI(MBB, MI, DL, TII.get(SH::MOVLM), SP)
       .addReg(Reg)
       .setMIFlag(MachineInstr::FrameSetup);
   }
@@ -283,7 +283,7 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
   for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
 
     MCRegister Reg = I.getReg();
-    BuildMI(MBB, MI, DL, TII.get(SH::MOVLRminciRn), SP)
+    BuildMI(MBB, MI, DL, TII.get(SH::MOVLM), SP)
       .addReg(Reg)
       .setMIFlag(MachineInstr::FrameDestroy);
   }
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 613e23fccb2d6..ca9b1bebcabb5 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -24,6 +24,7 @@
 #include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/DebugLog.h"
 
 #define DEBUG_TYPE "sh-isel"
@@ -142,11 +143,12 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
   auto DL = CurDAG->getDataLayout();
   MVT PtrVT = getTargetLowering()->getPointerTy(DL);
 
+  LLVM_DEBUG(dbgs() << "SelectAddr\n");
+
   // if the address is a frame index get the TargetFrameIndex.
   if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
     Disp = CurDAG->getTargetConstant(0, dl, MVT::i8);
-
     return true;
   }
 
@@ -171,7 +173,7 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
   // External Symbols
   if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
     SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
     ReplaceNode(N, Res);
     return true;
   }
@@ -179,7 +181,7 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
   // Global Addresses
   if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
     SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
     ReplaceNode(N, Res);
     return true;
   }
@@ -187,7 +189,7 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
   // Block Addresses
   if (auto *CPV = SFI->tryGetConstant((BlockAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
     SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLD8PCRn, DL, MVT::i32, TGA);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
     ReplaceNode(N, Res);
     return true;
   }
@@ -219,31 +221,31 @@ bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
     // TST would be faster in this case.
     if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
       if (C->getSExtValue() == 0) {
-        Res = CurDAG->getMachineNode(SH::TSTRmRn, DL, MVT::Glue, LHS, LHS);
+        Res = CurDAG->getMachineNode(SH::TST, DL, MVT::Glue, LHS, LHS);
         break;
       }
     }
-    Res = CurDAG->getMachineNode(SH::CMPEQRmRn, DL, MVT::Glue, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPEQ, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case ISD::SETUGE:
   case ISD::SETULT: {
-    Res = CurDAG->getMachineNode(SH::CMPHSRmRn, DL, MVT::Glue, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPHS, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case ISD::SETOGE:
   case ISD::SETOLT: {
-    Res = CurDAG->getMachineNode(SH::CMPGERmRn, DL, MVT::Glue, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPGE, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case ISD::SETUGT:
   case ISD::SETULE: {
-    Res = CurDAG->getMachineNode(SH::CMPGTRmRn, DL, MVT::Glue, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPGT, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case ISD::SETOGT:
   case ISD::SETOLE: {
-    Res = CurDAG->getMachineNode(SH::CMPHIRmRn, DL, MVT::Glue, LHS, RHS);
+    Res = CurDAG->getMachineNode(SH::CMPHI, DL, MVT::Glue, LHS, RHS);
     break;
   }
   }
@@ -331,7 +333,7 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
     SDValue GOT = CurDAG->getTargetExternalSymbol(
         "_GLOBAL_OFFSET_TABLE_", MVT::i32, SHII::MO_GOTPC);
     MachineSDNode *Res = 
-        CurDAG->getMachineNode(SH::MOVAD8PCR0, DL, MVT::i32, GOT);
+        CurDAG->getMachineNode(SH::MOVA, DL, MVT::i32, GOT);
     ReplaceNode(N, Res);
     return true;
   }
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 299285b73c5c4..78a63370a645e 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -89,6 +89,11 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::SREM, VT, Custom);
   }
 
+  // Multiplies have multiple lowerings depending on size.
+  for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
+    setOperationAction(ISD::MUL, VT, Custom);
+  }
+
   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
   setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
@@ -564,7 +569,7 @@ SDValue SuperHTargetLowering::LowerCallResult(
 //                              DIVISION LOWERING
 //===----------------------------------------------------------------------===//
 
-SDValue SuperHTargetLowering::LowerDiv(SDValue Op, SelectionDAG &DAG) const {
+SDValue SuperHTargetLowering::LowerDIV(SDValue Op, SelectionDAG &DAG) const {
   unsigned Opcode = Op->getOpcode();
   assert((Opcode == ISD::SDIV || Opcode == ISD::UDIV) &&
          "Invalid opcode for Div lowering");
@@ -625,6 +630,66 @@ SDValue SuperHTargetLowering::LowerDiv(SDValue Op, SelectionDAG &DAG) const {
 
 
 
+//===----------------------------------------------------------------------===//
+//                          MULTIPLICATION LOWERING
+//===----------------------------------------------------------------------===//
+SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
+  unsigned Opcode = Op->getOpcode();
+  assert((Opcode == ISD::MUL) && "Invalid opcode for MUL lowering");
+  SDLoc DL(Op);
+
+  EVT VT = Op->getValueType(0);
+  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
+
+  switch (VT.getSimpleVT().SimpleTy) {
+  default:
+    llvm_unreachable("Unexpected type for ");
+  case MVT::i8: {
+    SDValue MulOp = DAG.getNode(SH::MULS, DL, MVT::i32, Op.getValue(0), Op.getValue(1));
+    return DAG.getNode(SH::LDSMACL, DL, MVT::i32, MulOp);
+  }
+  case MVT::i16: {
+    SDValue MulOp = DAG.getNode(SH::MULS, DL, MVT::i32, Op.getValue(0), Op.getValue(1));
+    return DAG.getNode(SH::LDSMACL, DL, MVT::i32, MulOp);
+  }
+
+  case MVT::i32: {
+    // 32-bit multiplication requires lowering to __mulsi3
+    SDValue InChain = DAG.getEntryNode();
+
+    TargetLowering::ArgListTy Args;
+    for (SDValue const &Value : Op->op_values()) {
+      TargetLowering::ArgListEntry Entry(
+          Value, Value.getValueType().getTypeForEVT(*DAG.getContext()));
+      Args.push_back(Entry);
+    }
+
+    RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(RTLIB::MUL_I32);
+    if (LCImpl == RTLIB::Unsupported)
+      return SDValue();
+
+    SDValue Callee =
+        DAG.getExternalSymbol(LCImpl, getPointerTy(DAG.getDataLayout()));
+
+    Type *RetTy = (Type *)StructType::get(Ty, Ty);
+
+
+    TargetLowering::CallLoweringInfo CLI(DAG);
+    CLI.setDebugLoc(DL)
+        .setChain(InChain)
+        .setLibCallee(DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy,
+                      Callee, std::move(Args))
+        .setInRegister();
+
+    std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
+    return CallInfo.first;
+  }
+  }
+}
+
+
+
+
 //===----------------------------------------------------------------------===//
 //                              CUSTOM LOWERING
 //===----------------------------------------------------------------------===//
@@ -633,7 +698,9 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
   switch(Op->getOpcode()) {
   case ISD::UDIV:
   case ISD::SDIV:
-    return LowerDiv(Op, DAG);
+    return LowerDIV(Op, DAG);
+  case ISD::MUL:
+    return LowerMUL(Op, DAG);
   case ISD::GlobalAddress:
     return LowerGlobalAddress(Op, DAG);
   case ISD::ExternalSymbol:
@@ -656,38 +723,6 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 
-//===----------------------------------------------------------------------===//
-//                            Load/Store Lowering
-//===----------------------------------------------------------------------===//
-
-MachineBasicBlock *SuperHTargetLowering::insertLoad(MachineInstr &MI, 
-                                                    MachineBasicBlock *MBB) const {
-  DEBUG_FN_PRINT()
-  MachineFunction &MF = *MBB->getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
-  const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
-  const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
-
-  MachineOperand Dest = MI.getOperand(0);
-  MachineOperand Offset = MI.getOperand(1);
-
-  // Target index load.
-  if (Dest.isTargetIndex()) {
-
-  }
-  
-  MI.eraseFromParent();
-  return MBB;
-}
-
-MachineBasicBlock *SuperHTargetLowering::insertStore(MachineInstr &MI, 
-                                                     MachineBasicBlock *MBB) const {
-  DEBUG_FN_PRINT()
-
-  MI.eraseFromParent();
-  return MBB;
-}
-
 
 
 
@@ -712,7 +747,7 @@ MachineBasicBlock *SuperHTargetLowering::insertSELECTCC(MachineInstr &MI,
   // Lower True-False selection
   if (TrueV.isImm() && FalseV.isImm()) {
     if (TrueV.getImm() == 1 && FalseV.getImm() == 0) {
-      BuildMI(*MBB, BBI, DL, TII.get(SH::MOVTRn), SH::R0);
+      BuildMI(*MBB, BBI, DL, TII.get(SH::MOVT), SH::R0);
       MI.eraseFromParent();
       return MBB;
     }
@@ -797,14 +832,6 @@ SuperHTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
   case SH::Select16:
   case SH::Select32:
     return insertSELECTCC(MI, MBB);
-  case SH::LDI8:
-  case SH::LDI16:
-  case SH::LDI32:
-    return insertLoad(MI, MBB);
-  case SH::STI8:
-  case SH::STI16:
-  case SH::STI32:
-    return insertStore(MI, MBB);
   }
 
   return MBB;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 6f761b167f98e..a7b29f3640372 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -65,7 +65,8 @@ class SuperHTargetLowering : public TargetLowering  {
   SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
-  SDValue LowerDiv(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerDIV(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
 
   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 2b24bd6372234..e65d05a4c2276 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -133,7 +133,7 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 
   // If the targets are GPR registers, use MOV Rm, Rn.
   if (SH::GPRRegClass.contains(DestReg, SrcReg)) {
-    BuildMI(MBB, MI, DL, get(SH::MOVRmRn), DestReg)
+    BuildMI(MBB, MI, DL, get(SH::MOV), DestReg)
       .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   };
@@ -162,13 +162,13 @@ void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBl
   Register SrcStrReg;
   unsigned Opcode = 0;
   if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
-    Opcode = SH::MOVBR0D4Rni;
+    Opcode = SH::MOVBS4;
     SrcStrReg = SH::R0;
   } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
-    Opcode = SH::MOVWR0D4Rni;
+    Opcode = SH::MOVWS4;
     SrcStrReg = SH::R0;
   } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
-    Opcode = SH::MOVLRmD4Rni;
+    Opcode = SH::MOVLS4;
     SrcStrReg = SrcReg;
   } else {
     llvm_unreachable("Cannot store this register into a stack slot!");
@@ -176,16 +176,16 @@ void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBl
 
   // mov r14,r1
   // add #-<frame size>,r1
-  BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SH::R1)
+  BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SH::R1)
     .addReg(SH::R14);
-  BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI8Rn), SH::R1)
+  BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI), SH::R1)
     .addReg(SH::R1)
     .addImm(-(int)MFI.getStackSize());
 
   // mov srcreg,r0
   // mov.b/w r0,@(<offset>,r1)
   if (SrcStrReg != SrcReg) {
-    BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SrcStrReg)
+    BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SrcStrReg)
       .addReg(SrcReg, getKillRegState(isKill));
     BuildMI(MBB, MI, DebugLoc(), get(Opcode))
       .addReg(SH::R1)
@@ -221,13 +221,13 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
   unsigned Opcode = 0;
   Register DstStrReg;
   if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
-    Opcode = SH::MOVBD4RmiR0;
+    Opcode = SH::MOVBL4;
     DstStrReg = SH::R0;
   } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
-    Opcode = SH::MOVWD4RmiR0;
+    Opcode = SH::MOVWL4;
     DstStrReg = SH::R0;
   } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
-    Opcode = SH::MOVLD4RmiRn;
+    Opcode = SH::MOVLL4;
     DstStrReg = DestReg;
   } else {
     llvm_unreachable("Cannot load this register into a stack slot!");
@@ -235,9 +235,9 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
 
   // mov r14,r1
   // add #-<frame size>,r1
-  BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), SH::R1)
+  BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SH::R1)
     .addReg(SH::R14);
-  BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI8Rn), SH::R1)
+  BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI), SH::R1)
     .addReg(SH::R1)
     .addImm(-(int)MFI.getStackSize());
 
@@ -247,7 +247,7 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
     BuildMI(MBB, MI, DebugLoc(), get(Opcode))
       .addReg(SH::R1)
       .addImm(Offset);
-    BuildMI(MBB, MI, DebugLoc(), get(SH::MOVRmRn), DestReg)
+    BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), DestReg)
       .addReg(DstStrReg);
     return;
   }
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 93d03ebcf3aad..7e1c22e132a61 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -197,7 +197,15 @@ def IGPR    : SHIndirectRegOp<GPR, "">;
 def IGPRInc : SHIndirectRegOp<GPR, "Inc">;
 def IGPRDec : SHIndirectRegOp<GPR, "Dec">;
 
-// Addressing mode pattern reg+imm6
+// Register Indirect with Displacement @(disp,Rm)
+def memri : Operand<iPTR> {
+  let MIOperandInfo = (ops GPR, disp8);
+  let OperandType = "OPERAND_MEMORY";
+  let EncoderMethod = "getMemriOpValue";
+  let PrintMethod = "printMemri";
+}
+
+// Addressing mode pattern reg+disp
 let WantsRoot = true in
 def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
 
@@ -237,9 +245,7 @@ def HasSH4      : Predicate<"Subtarget->hasSH4Inst()">,
                   AssemblerPredicate<(all_of FeatureSH4)>;
 
 def HasSH4A     : Predicate<"Subtarget->hasSH4AInst()">,
-                  AssemblerPredicate<(all_of FeatureSH4A)>;
-
-
+                  AssemblerPredicate<(all_of FeatureSH4A)>;  
 
 
 //===--------------------------------------------------------------------------===//
@@ -247,62 +253,66 @@ def HasSH4A     : Predicate<"Subtarget->hasSH4AInst()">,
 //                          Data Transfer Instructions
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
+// NOTE:  The names of the instructions are taken from the SH manual's
+//        Pseudocode examples for each instruction.
+//        When adding new instructions, please keep this naming scheme.
+//===--------------------------------------------------------------------------===//
 
 // mov Rm, Rn
 let hasSideEffects = 0 in
-def MOVRmRn       : InstRmRn<0b0110000000000011,
+def MOV           : InstRmRn<0b0110000000000011,
                             (outs GPR:$Rn), (ins GPR:$Rm),
                             "mov $Rm,$Rn",
                             []>;
 
 // mov #imm:8, Rn
 let hasSideEffects = 0 in 
-def MOVI8Rn       : InstRnI8<0b1110000000000000,
+def MOVI          : InstRnI8<0b1110000000000000,
                             (outs GPR:$Rn), (ins imm8:$imm),
                             "mov $imm,$Rn",
                             [(set i32:$Rn, imm:$imm)]>;
 
 // mova @(disp, PC), R0
 let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
-def MOVAD8PCR0      : InstD8<0b1100011100000000,
+def MOVA          : InstD8<0b1100011100000000,
                             (outs), (ins pcrel8:$disp),
                             "mova $disp,r0",
                             []>;
 
 // mov.w @(disp,PC), Rn 
 let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
-def MOVWD8PCRn    : InstRnD8<0b1001000000000000,
+def MOVWI         : InstRnD8<0b1001000000000000,
                             (outs GPR:$Rn), (ins pcrel8:$disp),
                             "mov.w $disp,$Rn",
                             [(set i32:$Rn, (sextloadi16 constpool:$disp))]>;
 
 // mov.l @(disp,PC), Rn 
 let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
-def MOVLD8PCRn    : InstRnD8<0b1101000000000000,
+def MOVLI         : InstRnD8<0b1101000000000000,
                             (outs GPR:$Rn), (ins pcrel8:$disp),
                             "mov.l $disp,$Rn",
                             [(set i32:$Rn, (load constpool:$disp))]>;
 
 // movt Rn
-def MOVTRn          : InstRn<0b0000000000101001,
+def MOVT          : InstRn<0b0000000000101001,
                             (outs GPR:$Rn), (ins),
                             "movt $Rn",
                             []>;
 
 // swap.b Rm,Rn
-def SWAPBRmRn     : InstRmRn<0b0110000000001000,
+def SWAPB         : InstRmRn<0b0110000000001000,
                             (outs GPR:$Rn), (ins GPR:$Rm),
                             "swap.b $Rm,$Rn",
                             []>;
 
 // swap.w Rm,Rn
-def SWAPWRmRn     : InstRmRn<0b0110000000001001,
+def SWAPW         : InstRmRn<0b0110000000001001,
                             (outs GPR:$Rn), (ins GPR:$Rm),
                             "swap.w $Rm,$Rn",
                             []>;
 
 // xtrct Rm,Rn
-def XTRCTRmRn     : InstRmRn<0b0010000000001101,
+def XTRCT         : InstRmRn<0b0010000000001101,
                             (outs GPR:$Rn), (ins GPR:$Rm),
                             "xtrct $Rm,$Rn",
                             []>;
@@ -315,102 +325,102 @@ def XTRCTRmRn     : InstRmRn<0b0010000000001101,
 let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
 
   // mov.b @Rm, Rn
-  def MOVBRmiRn         : InstRmRn<0b0110000000000000,
+  def MOVBL             : InstRmRn<0b0110000000000000,
                                   (outs GPR:$Rn), (ins IGPR:$Rm),
                                   "mov.b $Rm,$Rn",
-                                  []>;
+                                  [(set i32:$Rn, (sextloadi8 IGPR:$Rm))]>;
 
   // mov.w @Rm, Rn
-  def MOVWRmiRn         : InstRmRn<0b0110000000000001,
+  def MOVWL             : InstRmRn<0b0110000000000001,
                                   (outs GPR:$Rn), (ins IGPR:$Rm),
                                   "mov.w $Rm,$Rn",
-                                  []>;
+                                  [(set i32:$Rn, (sextloadi16 IGPR:$Rm))]>;
 
   // mov.l @Rm, Rn
-  def MOVLRmiRn         : InstRmRn<0b0110000000000010,
+  def MOVLL             : InstRmRn<0b0110000000000010,
                                   (outs GPR:$Rn), (ins IGPR:$Rm),
                                   "mov.l $Rm,$Rn",
-                                  []>;
+                                  [(set i32:$Rn, (load IGPR:$Rm))]>;
 
   // mov.b @Rm+, Rn
   let isDelayIllegal = 1 in
-  def MOVBRminciRn      : InstRmRn<0b0110000000000100,
+  def MOVBP             : InstRmRn<0b0110000000000100,
                                   (outs GPR:$Rn), (ins IGPRInc:$Rm),
                                   "mov.b $Rm,$Rn",
                                   []>;
 
   // mov.w @Rm+, Rn
   let isDelayIllegal = 1 in
-  def MOVWRminciRn      : InstRmRn<0b0110000000000101,
+  def MOVWP             : InstRmRn<0b0110000000000101,
                                   (outs GPR:$Rn), (ins IGPRInc:$Rm),
                                   "mov.w $Rm,$Rn",
                                   []>;
 
   // mov.l @Rm+, Rn
   let isDelayIllegal = 1 in
-  def MOVLRminciRn      : InstRmRn<0b0110000000000110,
+  def MOVLP             : InstRmRn<0b0110000000000110,
                                   (outs GPR:$Rn), (ins IGPRInc:$Rm),
                                   "mov.l $Rm,$Rn",
                                   []>;
 
   // mov.b @(disp, Rm), R0
   let Defs = [R0] in
-  def MOVBD4RmiR0       : InstRmD4<0b1000010000000000,
-                                  (outs), (ins GPR:$Rm, disp4:$disp),
-                                  "mov.b @($disp,$Rm),R0",
-                                  []>;
+  def MOVBL4            : InstRmD4<0b1000010000000000,
+                                  (outs), (ins (memri $Rm, $disp):$src),
+                                  "mov.b $src,R0",
+                                  [(set R0, (sextloadi8 addr:$src))]>;
   
   // mov.w @(disp, Rm), R0
   let Defs = [R0] in
-  def MOVWD4RmiR0       : InstRmD4<0b1000010100000000,
-                                  (outs), (ins GPR:$Rm, disp4:$disp),
-                                  "mov.w @($disp,$Rm),R0",
-                                  []>;
+  def MOVWL4            : InstRmD4<0b1000010100000000,
+                                  (outs), (ins (memri $Rm, $disp):$src),
+                                  "mov.w $src,R0",
+                                  [(set R0, (sextloadi16 addr:$src))]>;
   
   // mov.l @(disp, Rm), Rn
-  def MOVLD4RmiRn     : InstRmRnD4<0b0101000000000000,
-                                  (outs GPR:$Rn), (ins GPR:$Rm, disp4:$disp),
-                                  "mov.l @($disp,$Rm),$Rn",
-                                  []>;
+  def MOVLL4          : InstRmRnD4<0b0101000000000000,
+                                  (outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                                  "mov.l $src,$Rn",
+                                  [(set i32:$Rn, (load addr:$src))]>;
 
   // mov.b @(R0,Rm),Rn
   let Uses = [R0] in
-  def MOVBR0RmiRn       : InstRmRn<0b0000000000001100,
+  def MOVBL0            : InstRmRn<0b0000000000001100,
                                   (outs GPR:$Rn), (ins GPR:$Rm),
                                   "mov.b @(R0,Rm),Rn",
                                   []>;
   
   // mov.w @(R0,Rm),Rn
   let Uses = [R0] in
-  def MOVWR0RmiRn       : InstRmRn<0b0000000000001101,
+  def MOVWL0            : InstRmRn<0b0000000000001101,
                                   (outs GPR:$Rn), (ins GPR:$Rm),
                                   "mov.w @(R0,$Rm),$Rn",
                                   []>;
   
   // mov.l @(R0,Rm),Rn
   let Uses = [R0] in
-  def MOVLR0RmiRn       : InstRmRn<0b0000000000001110,
+  def MOVLL0            : InstRmRn<0b0000000000001110,
                                   (outs GPR:$Rn), (ins GPR:$Rm),
                                   "mov.l @(R0,$Rm),$Rn",
                                   []>;
 
   // mov.b @(disp,GBR),R0
   let Defs = [R0], Uses = [GBR] in
-  def MOVBD12GBRiR0       : InstD8<0b1100010000000000,
+  def MOVBLG              : InstD8<0b1100010000000000,
                                   (outs), (ins disp12:$disp),
                                   "mov.b @($disp,GBR),R0",
                                   []>;
   
   // mov.w @(disp,GBR),R0
   let Defs = [R0], Uses = [GBR] in
-  def MOVWD12GBRiR0       : InstD8<0b1100010100000000,
+  def MOVWLG              : InstD8<0b1100010100000000,
                                   (outs), (ins disp12:$disp),
                                   "mov.w @($disp,GBR),R0",
                                   []>;
   
   // mov.l @(disp,GBR),R0
   let Defs = [R0], Uses = [GBR] in
-  def MOVLD12GBRiR0       : InstD8<0b1100011000000000,
+  def MOVLLG              : InstD8<0b1100011000000000,
                                   (outs), (ins disp12:$disp),
                                   "mov.l @($disp,GBR),R0",
                                   []>;
@@ -426,102 +436,102 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
 let hasSideEffects = 0, mayStore = 1 in {
 
   // mov.b Rm, @Rn
-  def MOVBRmRni         : InstRmRn<0b0010000000000000,
+  def MOVBS             : InstRmRn<0b0010000000000000,
                                   (outs), (ins GPR:$Rm, IGPR:$Rn),
                                   "mov.b $Rm,$Rn",
-                                  []>;
+                                  [(truncstorei8 i32:$Rm, i32:$Rn)]>;
 
   // mov.w Rm, @Rn
-  def MOVWRmRni         : InstRmRn<0b0010000000000001,
+  def MOVWS             : InstRmRn<0b0010000000000001,
                                   (outs), (ins GPR:$Rm, IGPR:$Rn),
                                   "mov.w $Rm,$Rn",
-                                  []>;
+                                  [(truncstorei16 i32:$Rm, i32:$Rn)]>;
 
   // mov.l Rm, @Rn
-  def MOVLRmRni         : InstRmRn<0b0010000000000010,
+  def MOVLS             : InstRmRn<0b0010000000000010,
                                   (outs), (ins GPR:$Rm, IGPR:$Rn),
                                   "mov.l $Rm,$Rn",
-                                  []>;
+                                  [/*(store i32:$Rm, i32:$Rn)*/]>;
 
   // mov.b Rm, @-Rn
   let isDelayIllegal = 1 in
-  def MOVBRmRndeci      : InstRmRn<0b0010000000000100,
+  def MOVBM             : InstRmRn<0b0010000000000100,
                                   (outs), (ins GPR:$Rm, IGPRDec:$Rn),
                                   "mov.b $Rm,$Rn",
                                   []>;
 
   // mov.w Rm, @-Rn
   let isDelayIllegal = 1 in
-  def MOVWRmRndeci      : InstRmRn<0b0010000000000101,
+  def MOVWM             : InstRmRn<0b0010000000000101,
                                   (outs), (ins GPR:$Rm, IGPRDec:$Rn),
                                   "mov.w $Rm,$Rn",
                                   []>;
 
   // mov.l Rm, @-Rn
   let isDelayIllegal = 1 in
-  def MOVLRmRndeci      : InstRmRn<0b0010000000000110,
+  def MOVLM             : InstRmRn<0b0010000000000110,
                                   (outs), (ins GPR:$Rm, IGPRDec:$Rn),
                                   "mov.l $Rm,$Rn",
                                   []>;
   
   // mov.b R0, @(disp, Rn)
   let Uses = [R0] in
-  def MOVBR0D4Rni       : InstRnD4<0b1000000000000000,
-                                  (outs), (ins GPR:$Rn, disp4:$disp),
-                                  "mov.b R0,@($disp,$Rn)",
-                                  []>;
+  def MOVBS4            : InstRnD4<0b1000000000000000,
+                                  (outs), (ins (memri $Rn, $disp):$dst),
+                                  "mov.b r0,$dst",
+                                  [/*(truncstorei8 i32, addr:$dst)*/]>;
   
   // mov.w R0, @(disp, Rn)
   let Uses = [R0] in
-  def MOVWR0D4Rni       : InstRnD4<0b1000000100000000,
-                                  (outs), (ins GPR:$Rn, disp4:$disp),
-                                  "mov.w R0,@($disp,$Rn)",
-                                  []>;
+  def MOVWS4            : InstRnD4<0b1000000100000000,
+                                  (outs), (ins (memri $Rn, $disp):$dst),
+                                  "mov.w r0,$dst",
+                                  [/*(truncstorei16 i32, addr:$dst)*/]>;
   
   // mov.l Rm, @(disp, Rn)
-  def MOVLRmD4Rni     : InstRmRnD4<0b0001000000000000,
-                                  (outs), (ins GPR:$Rn, GPR:$Rm, disp4:$disp),
-                                  "mov.l $Rm,@($disp,$Rn)",
-                                  []>;
+  def MOVLS4          : InstRmRnD4<0b0001000000000000,
+                                  (outs), (ins GPR:$Rm, (memri $Rn, $disp):$dst),
+                                  "mov.l $Rm,$dst",
+                                  [(store i32:$Rm, addr:$dst)]>;
 
   // mov.b Rm,@(R0,Rn)
   let Uses = [R0] in
-  def MOVBRmR0Rni       : InstRmRn<0b0000000000000100,
+  def MOVBS0            : InstRmRn<0b0000000000000100,
                                   (outs), (ins GPR:$Rm, GPR:$Rn),
                                   "mov.b $Rm,@(R0,$Rn)",
                                   []>;
   
   // mov.w Rm,@(R0,Rn)
   let Uses = [R0] in
-  def MOVWRmR0Rni       : InstRmRn<0b0000000000000101,
+  def MOVWS0            : InstRmRn<0b0000000000000101,
                                   (outs), (ins GPR:$Rm, GPR:$Rn),
                                   "mov.w $Rm,@(R0,$Rn)",
                                   []>;
   
   // mov.l Rm,@(R0,Rn)
   let Uses = [R0] in
-  def MOVLRmR0Rni       : InstRmRn<0b0000000000000110,
+  def MOVLS0            : InstRmRn<0b0000000000000110,
                                   (outs), (ins GPR:$Rm, GPR:$Rn),
                                   "mov.l $Rm,@(R0,$Rn)",
                                   []>;
 
   // mov.b R0,@(disp,GBR)
   let Uses = [R0, GBR] in
-  def MOVBR0D12GBRi       : InstD8<0b1100000000000000,
+  def MOVBSG              : InstD8<0b1100000000000000,
                                   (outs), (ins disp12:$disp),
                                   "mov.b R0,@($disp,GBR)",
                                   []>;
   
   // mov.w R0,@(disp,GBR)
   let Uses = [R0, GBR] in
-  def MOVWR0D12GBRi       : InstD8<0b1100000100000000,
+  def MOVWSG              : InstD8<0b1100000100000000,
                                   (outs), (ins disp12:$disp),
                                   "mov.w R0,@($disp,GBR)",
                                   []>;
   
   // mov.l R0,@(disp,GBR)
   let Uses = [R0, GBR] in
-  def MOVLR0D12GBRi       : InstD8<0b1100001000000000,
+  def MOVLSG              : InstD8<0b1100001000000000,
                                   (outs), (ins disp12:$disp),
                                   "mov.l R0,@($disp,GBR)",
                                   []>;
@@ -545,27 +555,27 @@ let hasSideEffects = 0, mayStore = 1 in {
 let hasSideEffects = 0, Constraints = "$src = $Rn" in {
   
   // add Rm, Rn
-  def ADDRmRn       : InstRmRn<0b0011000000001100, 
+  def ADD           : InstRmRn<0b0011000000001100, 
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "add $Rm,$Rn",
                               [(set i32:$Rn, (add i32:$Rm, i32:$src))]>;
   
   // add imm:8, Rn
-  def ADDI8Rn       : InstRnI8<0b0111000000000000, 
+  def ADDI          : InstRnI8<0b0111000000000000, 
                               (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
                               "add $imm,$Rn",
                               [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
 
   // addc Rm, Rn
   let Defs = [SR], Uses = [SR], isCommutable = 1 in
-  def ADDCRmRn      : InstRmRn<0b0011000000001110,
+  def ADDC          : InstRmRn<0b0011000000001110,
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "addc $Rm,$Rn",
                               [(set i32:$Rn, (adde i32:$Rm, i32:$src))]>;
   
   // addv Rm, Rn
   let Defs = [SR], isCommutable = 1 in
-  def ADDVRmRn      : InstRmRn<0b0011000000001111,
+  def ADDV          : InstRmRn<0b0011000000001111,
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "addv $Rm,$Rn",
                               [(set i32:$Rn, (addc i32:$Rm, i32:$src))]>;
@@ -581,28 +591,28 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
 let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 
   // sub Rm, Rn
-  def SUBRmRn       : InstRmRn<0b0011000000001000,
+  def SUB           : InstRmRn<0b0011000000001000,
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "sub $Rm,$Rn",
                               [(set i32:$Rn, (sub i32:$Rm, i32:$src))]>;
 
   // subc Rm, Rn
   let Defs = [SR], Uses = [SR] in
-  def SUBCRmRn      : InstRmRn<0b0011000000001010,
+  def SUBC          : InstRmRn<0b0011000000001010,
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "subc $Rm,$Rn",
                               [(set i32:$Rn, (sube i32:$Rm, i32:$src))]>;
 
   // subv Rm, Rn
   let Defs = [SR] in
-  def SUBVRmRn      : InstRmRn<0b0011000000001011,
+  def SUBV          : InstRmRn<0b0011000000001011,
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "subv $Rm,$Rn",
                               [(set i32:$Rn, (subc i32:$Rm, i32:$src))]>;
   
   // dt Rn
   let Defs = [SR] in
-  def DTRn            : InstRn<0b0100000000010000,
+  def DT              : InstRn<0b0100000000010000,
                               (outs GPR:$Rn), (ins GPR:$src),
                               "dt $Rn",
                               [(set i32:$Rn, (sub i32:$src, -1))]>;
@@ -611,14 +621,14 @@ let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 let hasSideEffects = 0 in {
 
   // neg Rm, Rn
-  def NEGRmRn       : InstRmRn<0b0110000000001011,
+  def NEG           : InstRmRn<0b0110000000001011,
                               (outs GPR:$Rn), (ins GPR:$Rm),
                               "neg $Rm,$Rn",
                               [(set i32:$Rn, (ineg i32:$Rm))]>;
 
   // negc Rm, Rn
   let Defs = [SR], Uses = [SR] in
-  def NEGCRmRn      : InstRmRn<0b0110000000001010,
+  def NEGC          : InstRmRn<0b0110000000001010,
                               (outs GPR:$Rn), (ins GPR:$Rm),
                               "negc $Rm,$Rn",
                               [(set i32:$Rn, (ineg i32:$Rm))]>;
@@ -634,50 +644,50 @@ let hasSideEffects = 0 in {
 let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
 
   // mac.w @Rm+, @Rn+
-  let Defs = [MACL] in
-  def MACWRmRn      : InstRmRn<0b0100000000001111, 
+  let Defs = [MACLO] in
+  def MACW      : InstRmRn<0b0100000000001111, 
                               (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
                               "mac.w $Rm,$Rn",
                               []>;
 
   // mac.l @Rm+, @Rn+
-  let Defs = [MACL, MACH] in
-  def MACLRmRn      : InstRmRn<0b0000000000001111, 
+  let Defs = [MACLO, MACHI] in
+  def MACL          : InstRmRn<0b0000000000001111, 
                               (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
                               "mac.l $Rm,$Rn",
                               []>;
 
   // mul.l Rm, Rn
-  let Defs = [MACL] in
-  def MULLRmRn      : InstRmRn<0b0000000000000111, 
+  let Defs = [MACLO] in
+  def MULL          : InstRmRn<0b0000000000000111, 
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "mul.l $Rm,$Rn",
                               []>;
 
   // muls.w Rm, Rn
-  let Defs = [MACL] in
-  def MULSWRmRn     : InstRmRn<0b0010000000001111, 
+  let Defs = [MACLO] in
+  def MULS          : InstRmRn<0b0010000000001111, 
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "muls.w $Rm,$Rn",
                               []>;
 
   // mulu.w Rm, Rn
-  let Defs = [MACL] in
-  def MULUWRmRn     : InstRmRn<0b0010000000001110, 
+  let Defs = [MACLO] in
+  def MULU          : InstRmRn<0b0010000000001110, 
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "mulu.w $Rm,$Rn",
                               []>;
 
   // dmuls.l Rm, Rn
-  let Defs = [MACL, MACH] in
-  def DMULSLRmRn    : InstRmRn<0b0011000000001101, 
+  let Defs = [MACLO, MACHI] in
+  def DMULS         : InstRmRn<0b0011000000001101, 
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "dmuls.l $Rm,$Rn",
                               []>;
 
   // dmulu.l Rm, Rn
-  let Defs = [MACL, MACH] in
-  def DMULULRmRn    : InstRmRn<0b0011000000000101, 
+  let Defs = [MACLO, MACHI] in
+  def DMULU         : InstRmRn<0b0011000000000101, 
                               (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                               "dmulu.l $Rm,$Rn",
                               []>;
@@ -694,7 +704,7 @@ let hasSideEffects = 0, isCommutable = 1 in {
 
   // div0s Rm, Rn
   let Defs = [SR] in
-  def DIV0SRmRn     : InstRmRn<0b0010000000000111, 
+  def DIV0S         : InstRmRn<0b0010000000000111, 
                               (outs), (ins GPR:$Rm, GPR:$Rn),
                               "div0s $Rm,$Rn",
                               []>;
@@ -708,7 +718,7 @@ let hasSideEffects = 0, isCommutable = 1 in {
 
   // div1 Rm, Rn
   let Defs = [SR] in
-  def DIV1RmRn      : InstRmRn<0b0011000000000100, 
+  def DIV1          : InstRmRn<0b0011000000000100, 
                               (outs GPR:$Rn), (ins GPR:$Rm),
                               "div1 $Rm,$Rn",
                               []>;
@@ -722,27 +732,27 @@ let hasSideEffects = 0, isCommutable = 1 in {
 //===--------------------------------------------------------------------------===//
   
 // exts.b Rm, Rn
-def EXTSBRmRn       : InstRmRn<0b0110000000001110, 
+def EXTSB           : InstRmRn<0b0110000000001110, 
                               (outs GPR:$Rn), (ins GPR:$Rm),
                               "exts.b $Rm,$Rn",
                               [(set i32:$Rn, (sext i8:$Rm))]>;
 
 // exts.w Rm, Rn
-def EXTSWRmRn       : InstRmRn<0b0110000000001111, 
+def EXTSW           : InstRmRn<0b0110000000001111, 
                               (outs GPR:$Rn), (ins GPR:$Rm),
                               "exts.w $Rm,$Rn",
-                             [(set i32:$Rn, (sext i16:$Rm))]>;
+                              [(set i32:$Rn, (sext i16:$Rm))]>;
 
 // extu.b Rm, Rn
-def EXTUBRmRn       : InstRmRn<0b0110000000001100, 
-                             (outs GPR:$Rn), (ins GPR:$Rm),
-                             "extu.b $Rm,$Rn",
-                             [(set i32:$Rn, (zext i8:$Rm))]>;
+def EXTUB           : InstRmRn<0b0110000000001100, 
+                              (outs GPR:$Rn), (ins GPR:$Rm),
+                              "extu.b $Rm,$Rn",
+                              [(set i32:$Rn, (zext i8:$Rm))]>;
 
 // extu.w Rm, Rn
-def EXTUWRmRn       : InstRmRn<0b0110000000001101, 
+def EXTUW           : InstRmRn<0b0110000000001101, 
                               (outs GPR:$Rn), (ins GPR:$Rm),
-                             "extu.w $Rm,$Rn",
+                              "extu.w $Rm,$Rn",
                               [(set i32:$Rn, (zext i16:$Rm))]>;
 
 
@@ -755,63 +765,63 @@ def EXTUWRmRn       : InstRmRn<0b0110000000001101,
 
 // cmp/eq #imm,R0
 let Defs = [R0, SR] in
-def CMPEQI8R0         : InstI8<0b1000100000000000,
+def CMPIM             : InstI8<0b1000100000000000,
                               (outs), (ins imm8:$imm),
                               "cmp/eq #imm,R0",
                               []>;
 
 // cmp/eq Rm,Rn
 let Defs = [SR] in
-def CMPEQRmRn       : InstRmRn<0b0011000000000000,
+def CMPEQ           : InstRmRn<0b0011000000000000,
                               (outs), (ins GPR:$Rm, GPR:$Rn),
                               "cmp/eq $Rm,$Rn",
                               []>;
 
 // cmp/hs Rm,Rn
 let Defs = [SR] in
-def CMPHSRmRn       : InstRmRn<0b0011000000000010,
+def CMPHS           : InstRmRn<0b0011000000000010,
                               (outs), (ins GPR:$Rm, GPR:$Rn),
                               "cmp/hs $Rm,$Rn",
                               []>;
 
 // cmp/ge Rm,Rn
 let Defs = [SR] in
-def CMPGERmRn       : InstRmRn<0b0011000000000011,
+def CMPGE           : InstRmRn<0b0011000000000011,
                               (outs), (ins GPR:$Rm, GPR:$Rn),
                               "cmp/ge $Rm,$Rn",
                               []>;
 
 // cmp/hi Rm,Rn
 let Defs = [SR] in
-def CMPHIRmRn       : InstRmRn<0b0011000000000110,
+def CMPHI           : InstRmRn<0b0011000000000110,
                               (outs), (ins GPR:$Rm, GPR:$Rn),
                               "cmp/hi $Rm,$Rn",
                               []>;
 
 // cmp/gt Rm,Rn
 let Defs = [SR] in
-def CMPGTRmRn       : InstRmRn<0b0011000000000111,
+def CMPGT           : InstRmRn<0b0011000000000111,
                               (outs), (ins GPR:$Rm, GPR:$Rn),
                               "cmp/gt $Rm,$Rn",
                               []>;
 
 // cmp/pl Rn
 let Defs = [SR] in
-def CMPPLRn           : InstRn<0b0100000000010101,
+def CMPPL             : InstRn<0b0100000000010101,
                               (outs), (ins GPR:$Rn),
                               "cmp/pl $Rn",
                               []>;
 
 // cmp/pz Rn
 let Defs = [SR] in
-def CMPPZRn           : InstRn<0b0100000000010001,
+def CMPPZ             : InstRn<0b0100000000010001,
                               (outs), (ins GPR:$Rn),
                               "cmp/pz $Rn",
                               []>;
 
 // cmp/str Rm,Rn
 let Defs = [SR] in
-def CMPSTRRmRn      : InstRmRn<0b0010000000001100,
+def CMPSTR          : InstRmRn<0b0010000000001100,
                               (outs), (ins GPR:$Rm, GPR:$Rn),
                               "cmp/str $Rm,$Rn",
                               []>;
@@ -829,60 +839,94 @@ def CMPSTRRmRn      : InstRmRn<0b0010000000001100,
 
 // and Rm,Rn
 let Constraints = "$src = $Rn" in
-def ANDRmRn       : InstRmRn<0b0010000000001001, 
+def AND             : InstRmRn<0b0010000000001001, 
                             (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                             "and $Rm,$Rn",
                             [(set i32:$Rn, (and i32:$Rm, i32:$src))]>;
 // and #imm,R0
 let Defs = [R0], Uses = [R0] in
-def ANDI8R0         : InstI8<0b1100100100000000, 
+def ANDI            : InstI8<0b1100100100000000, 
                             (outs), (ins imm8:$imm),
                             "and $imm,R0",
                             []>;
+// and #imm,@(R0,GBR)
+let Uses = [R0, GBR] in
+def ANDM            : InstI8<0b1100110100000000, 
+                            (outs), (ins imm8:$imm),
+                            "and $imm,@(r0,gbr)",
+                            []>;
 
 // not Rm,Rn
-def NOTRmRn       : InstRmRn<0b0110000000000111, 
+def NOT           : InstRmRn<0b0110000000000111, 
                             (outs GPR:$Rn), (ins GPR:$Rm),
                             "not $Rm,$Rn",
                             [(set i32:$Rn, (not i32:$Rm))]>;
 
 // or Rm,Rn
 let Constraints = "$src = $Rn" in
-def ORRmRn        : InstRmRn<0b0010000000001011, 
+def OR            : InstRmRn<0b0010000000001011, 
                             (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                             "or $Rm,$Rn",
                             [(set i32:$Rn, (or i32:$Rm, i32:$src))]>;
 // or #imm,R0
 let Defs = [R0], Uses = [R0] in
-def ORI8R0          : InstI8<0b1100101100000000, 
+def ORI             : InstI8<0b1100101100000000, 
                             (outs), (ins imm8:$imm),
                             "or $imm,R0",
                             []>;
+// or.b #imm,@(R0,GBR)
+let Uses = [R0, GBR] in
+def ORM             : InstI8<0b1100111100000000, 
+                            (outs), (ins imm8:$imm),
+                            "or.b $imm,@(r0,gbr)",
+                            []>;
 
 // xor Rm,Rn
 let Constraints = "$src = $Rn" in
-def XORRmRn       : InstRmRn<0b0010000000001010, 
+def XOR           : InstRmRn<0b0010000000001010, 
                             (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
                             "xor $Rm,$Rn",
                             [(set i32:$Rn, (xor i32:$Rm, i32:$src))]>;
+
 // xor #imm,R0
 let Defs = [R0], Uses = [R0] in
-def XORI8R0         : InstI8<0b1100101000000000, 
+def XORI            : InstI8<0b1100101000000000, 
+                            (outs), (ins imm8:$imm),
+                            "xor $imm,r0",
+                            []>;
+
+// xor.b #imm,@(R0,GBR)
+let Defs = [R0], Uses = [R0] in
+def XORM            : InstI8<0b1100111000000000, 
                             (outs), (ins imm8:$imm),
-                            "xor $imm,R0",
+                            "xor.b $imm,@(r0,gbr)",
+                            []>;
+
+// tas.b @Rn
+let Defs = [SR] in
+def TAS             : InstRn<0b0010000000001000, 
+                            (outs), (ins IGPR:$Rn),
+                            "tas.b $Rn",
                             []>;
 
 // tst Rm,Rn
 let Defs = [SR] in
-def TSTRmRn       : InstRmRn<0b0010000000001000, 
+def TST           : InstRmRn<0b0010000000001000, 
                             (outs), (ins GPR:$Rm, GPR:$Rn),
                             "tst $Rm,$Rn",
                             []>;
 // tst #imm,R0
 let Defs = [SR], Uses = [R0] in
-def TSTI8R0         : InstI8<0b1100100000000000, 
+def TSTI            : InstI8<0b1100100000000000, 
+                            (outs), (ins imm8:$imm),
+                            "tst $imm,r0",
+                            []>;
+
+// tst.b #imm,@(R0,GBR)
+let Defs = [SR], Uses = [R0, GBR] in
+def TSTM            : InstI8<0b1100110000000000, 
                             (outs), (ins imm8:$imm),
-                            "tst $imm,R0",
+                            "tst.b $imm,@(r0,gbr)",
                             []>;
 
 
@@ -899,93 +943,93 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
 
   // rotcl Rn
   let Defs = [SR] in
-  def ROTCLRn         : InstRn<0b0100000000100100, 
+  def ROTCL           : InstRn<0b0100000000100100, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "rotcl $Rn",
                               []>;
 
   // rotcr Rn
   let Defs = [SR] in
-  def ROTCRRn         : InstRn<0b0100000000100101, 
+  def ROTCR           : InstRn<0b0100000000100101, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "rotcr $Rn",
                               []>;
 
   // rotl Rn
   let Defs = [SR] in
-  def ROTLRn          : InstRn<0b0100000000000100, 
+  def ROTL            : InstRn<0b0100000000000100, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "rotl $Rn",
                               [(set i32:$Rn, (rotl i32:$src, (i8 1)))]>;
 
   // rotr Rn
   let Defs = [SR] in
-  def ROTRRn          : InstRn<0b0100000000000101, 
+  def ROTR            : InstRn<0b0100000000000101, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "rotr $Rn",
                               [(set i32:$Rn, (rotr i32:$src, (i8 1)))]>;
 
   // shal Rn
   let Defs = [SR] in
-  def SHALRn          : InstRn<0b0100000000100000, 
+  def SHAL            : InstRn<0b0100000000100000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shal $Rn",
                               []>;
 
   // shar Rn
   let Defs = [SR] in
-  def SHARRn          : InstRn<0b0100000000100001, 
+  def SHAR            : InstRn<0b0100000000100001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shar $Rn",
                               [(set i32:$Rn, (sra i32:$src, (i8 1)))]>;
 
   // shll Rn
   let Defs = [SR] in
-  def SHLLRn          : InstRn<0b0100000000000000, 
+  def SHLL            : InstRn<0b0100000000000000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll $Rn",
                               [(set i32:$Rn, (shl i32:$src, (i8 1)))]>;
 
   // shll2 Rn
   let Defs = [SR] in
-  def SHLL2Rn          : InstRn<0b0100000000001000, 
+  def SHLL2           : InstRn<0b0100000000001000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll2 $Rn",
                               [(set i32:$Rn, (shl i32:$src, (i8 2)))]>;
 
   // shll8 Rn
-  def SHLL8Rn          : InstRn<0b0100000000011000, 
+  def SHLL8           : InstRn<0b0100000000011000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll8 $Rn",
                               [(set i32:$Rn, (shl i32:$src, (i8 8)))]>;
 
   // shll16 Rn
-  def SHLL16Rn          : InstRn<0b0100000000101000, 
+  def SHLL16          : InstRn<0b0100000000101000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll16 $Rn",
                               [(set i32:$Rn, (shl i32:$src, (i8 16)))]>;
 
   // shlr Rn
   let Defs = [SR] in
-  def SHLRRn          : InstRn<0b0100000000000001, 
+  def SHLR            : InstRn<0b0100000000000001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr $Rn",
                               [(set i32:$Rn, (srl i32:$src, (i8 1)))]>;
 
   // shlr2 Rn
-  def SHLR2Rn          : InstRn<0b0100000000001001, 
+  def SHLR2           : InstRn<0b0100000000001001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr2 $Rn",
                               [(set i32:$Rn, (srl i32:$src, (i8 2)))]>;
 
   // shlr8 Rn
-  def SHLR8Rn          : InstRn<0b0100000000011001, 
+  def SHLR8           : InstRn<0b0100000000011001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr8 $Rn",
                               [(set i32:$Rn, (srl i32:$src, (i8 8)))]>;
 
   // shlr16 Rn
-  def SHLR16Rn          : InstRn<0b0100000000101001, 
+  def SHLR16          : InstRn<0b0100000000101001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr16 $Rn",
                               [(set i32:$Rn, (srl i32:$src, (i8 16)))]>;
@@ -1062,8 +1106,8 @@ let isTerminator = 1 in {
 //===--------------------------------------------------------------------------===//
 
 let isCall = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in {
-  let Uses = [SR, GBR] in
-  def JSRRmi          : InstRm<0b0100000000001011,
+  let Uses = [PR, PC] in
+  def JSR             : InstRm<0b0100000000001011,
                               (outs), (ins IGPR:$Rm),
                               "jsr $Rm",
                               [(SHCall IGPR:$Rm)]>;
@@ -1103,84 +1147,84 @@ def CLRT                : Inst<0b0000000000001000, (outs), (ins), "clrt", []>;
 
 // ldc Rm, SR
 let Defs = [SR], isDelayIllegal = 1 in
-def LDCRmSR           : InstRm<0b0100000000001110, 
+def LDCSR             : InstRm<0b0100000000001110, 
                               (outs), (ins GPR:$Rm), 
                               "ldc $Rm,SR",
                               []>;
 
 // ldc.l @Rm+, SR
 let Defs = [SR], isDelayIllegal = 1 in
-def LDCLRminciSR      : InstRm<0b0100000000000111, 
+def LDCMSR            : InstRm<0b0100000000000111, 
                               (outs), (ins IGPRInc:$Rm), 
                               "ldc.l $Rm,SR",
                               []>;
 
 // ldc Rm, GBR
 let Defs = [GBR] in
-def LDCRmGBR          : InstRm<0b0100000000011110, 
+def LDCGBR            : InstRm<0b0100000000011110, 
                               (outs), (ins GPR:$Rm), 
                               "ldc $Rm,GBR",
                               []>;
 
 // ldc.l @Rm+, GBR
 let Defs = [GBR] in
-def LDCLRminciGBR     : InstRm<0b0100000000010111, 
+def LDCMGBR           : InstRm<0b0100000000010111, 
                               (outs), (ins IGPRInc:$Rm), 
                               "ldc.l $Rm,GBR",
                               []>;
 
 // ldc Rm, VBR
 let Defs = [VBR], isDelayIllegal = 1 in
-def LDCRmVBR          : InstRm<0b0100000000101110, 
+def LDCVBR            : InstRm<0b0100000000101110, 
                               (outs), (ins GPR:$Rm), 
                               "ldc $Rm,VBR",
                               []>;
 
 // ldc.l @Rm+, VBR
 let Defs = [VBR], isDelayIllegal = 1 in
-def LDCLRminciVBR     : InstRm<0b0100000000100111, 
+def LDCMVBR           : InstRm<0b0100000000100111, 
                               (outs), (ins IGPRInc:$Rm), 
                               "ldc.l $Rm,VBR",
                               []>;
 
 // lds Rm, MACH
-let Defs = [MACH] in
-def LDSRmMACH         : InstRm<0b0100000000001010, 
+let Defs = [MACHI] in
+def LDSMACH           : InstRm<0b0100000000001010, 
                               (outs), (ins GPR:$Rm), 
                               "lds $Rm,MACH",
                               []>;
 
 // lds.l @Rm+, MACH
-let Defs = [MACH] in
-def LDSLRminciMACH    : InstRm<0b0100000000000110, 
+let Defs = [MACHI] in
+def LDSMMACH           : InstRm<0b0100000000000110, 
                               (outs), (ins IGPRInc:$Rm), 
                               "lds.l $Rm,MACH",
                               []>;
 
 // lds Rm, MACL
-let Defs = [MACH] in
-def LDSRmMACL         : InstRm<0b0100000000011010, 
+let Defs = [MACLO] in
+def LDSMACL           : InstRm<0b0100000000011010, 
                               (outs), (ins GPR:$Rm), 
                               "lds $Rm,MACL",
                               []>;
 
 // lds.l @Rm+, MACL
-let Defs = [MACH] in
-def LDSLRminciMACL    : InstRm<0b0100000000010110, 
+let Defs = [MACLO] in
+def LDSMMACL          : InstRm<0b0100000000010110, 
                               (outs), (ins IGPRInc:$Rm), 
                               "lds.l $Rm,MACL",
                               []>;
 
 // lds Rm, PR
 let Defs = [PR] in
-def LDSRmPR           : InstRm<0b0100000000101010, 
+def LDSPR             : InstRm<0b0100000000101010, 
                               (outs), (ins GPR:$Rm), 
                               "lds $Rm,PR",
                               []>;
 
 // lds.l @Rm+, PR
 let Defs = [PR] in
-def LDSLRminciPR      : InstRm<0b0100000000100110, 
+def LDSMPR            : InstRm<0b0100000000100110, 
                               (outs), (ins IGPRInc:$Rm), 
                               "lds.l $Rm,PR",
                               []>;
@@ -1203,91 +1247,91 @@ def SLEEP               : Inst<0b0000000000011011, (outs), (ins), "sleep", []>;
 
 // stc SR,Rn
 let Uses = [SR], isDelayIllegal = 1 in
-def STCSRRn           : InstRn<0b0000000000000010, 
+def STCSR             : InstRn<0b0000000000000010, 
                               (outs GPR:$Rn), (ins), 
                               "stc SR,$Rn",
                               []>;
 
 // stc.l SR, at -Rn
 let Uses = [SR], isDelayIllegal = 1 in
-def STCLSRRndeci      : InstRn<0b0100000000000011, 
+def STCMSR            : InstRn<0b0100000000000011, 
                               (outs IGPRDec:$Rn), (ins), 
                               "stc.l SR,$Rn",
                               []>;
 
 // stc GBR,Rn
 let Uses = [GBR] in
-def STCGBRRn          : InstRn<0b0000000000010010, 
+def STCGBR          : InstRn<0b0000000000010010, 
                               (outs GPR:$Rn), (ins), 
                               "stc GBR,$Rn",
                               []>;
 
 // stc.l GBR, at -Rn
 let Uses = [GBR] in
-def STCLGBRRndeci     : InstRn<0b0100000000010011, 
+def STCMGBR           : InstRn<0b0100000000010011, 
                               (outs IGPRDec:$Rn), (ins), 
                               "stc.l GBR,$Rn",
                               []>;
 
 // stc VBR,Rn
 let Uses = [VBR], isDelayIllegal = 1 in
-def STCVBRRn          : InstRn<0b0000000000100010, 
+def STCVBR            : InstRn<0b0000000000100010, 
                               (outs GPR:$Rn), (ins), 
                               "stc VBR,$Rn",
                               []>;
 
 // stc.l VBR, at -Rn
 let Uses = [VBR], isDelayIllegal = 1 in
-def STCLVBRRndeci     : InstRn<0b0100000000100011, 
+def STCMVBR           : InstRn<0b0100000000100011, 
                               (outs IGPRDec:$Rn), (ins), 
                               "stc.l VBR,$Rn",
                               []>;
 
 // sts MACH,Rn
-let Uses = [MACH] in
-def STSMACHRn         : InstRn<0b0000000000001010, 
+let Uses = [MACHI] in
+def STSMACH           : InstRn<0b0000000000001010, 
                               (outs GPR:$Rn), (ins), 
                               "sts MACH,$Rn",
                               []>;
 
 // sts.l MACH, at -Rn
-let Uses = [MACH] in
-def STSLMACHRndeci    : InstRn<0b0100000000000010, 
+let Uses = [MACHI] in
+def STSMMACH          : InstRn<0b0100000000000010, 
                               (outs IGPRDec:$Rn), (ins), 
                               "sts.l MACH,$Rn",
                               []>;
 
 // sts MACL,Rn
-let Uses = [MACL] in
-def STSMACLRn         : InstRn<0b0000000000011010, 
+let Uses = [MACLO] in
+def STSMACL           : InstRn<0b0000000000011010, 
                               (outs GPR:$Rn), (ins), 
                               "sts MACL,$Rn",
                               []>;
 
 // sts.l MACL, at -Rn
-let Uses = [MACL] in
-def STSLMACLRndeci    : InstRn<0b0100000000010010, 
+let Uses = [MACLO] in
+def STSMMACL          : InstRn<0b0100000000010010, 
                               (outs IGPRDec:$Rn), (ins), 
                               "sts.l MACL,$Rn",
                               []>;
 
 // sts PR,Rn
 let Uses = [PR] in
-def STSPRRn           : InstRn<0b0000000000101010, 
+def STSPR             : InstRn<0b0000000000101010, 
                               (outs GPR:$Rn), (ins), 
                               "sts PR,$Rn",
                               []>;
 
 // sts.l PR, at -Rn
 let Uses = [PR] in
-def STSLPRRndeci      : InstRn<0b0100000000100010, 
+def STSMPR            : InstRn<0b0100000000100010, 
                               (outs IGPRDec:$Rn), (ins), 
                               "sts.l PR,$Rn",
                               []>;
 
 // trapa #imm
 let Defs = [PC], isCall = 1 in
-def TRAPAI8           : InstI8<0b1100001100000000, 
+def TRAPA             : InstI8<0b1100001100000000, 
                               (outs), (ins imm8:$imm), 
                               "trapa $imm",
                               []>;
@@ -1326,7 +1370,7 @@ include "SuperHInstrDSP.td"
 // def : Pat<(i32 (sextloadi1  i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
 // def : Pat<(i32 (sextloadi8  i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
 // def : Pat<(i32 (sextloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
-// 
+
 // def : Pat<(sext_inreg i32:$src, i1),  (EXTSBRmRn i32:$src)>;
 // def : Pat<(sext_inreg i32:$src, i8),  (EXTSBRmRn i32:$src)>;
 // def : Pat<(sext_inreg i32:$src, i16), (EXTSWRmRn i32:$src)>;
@@ -1346,40 +1390,6 @@ include "SuperHInstrDSP.td"
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
-//===--------------------------------------------------------------------------===//
-// Loads & Stores
-//===--------------------------------------------------------------------------===//
-
-def LDI8          : SHLoadPseudo<(outs GPR:$dst),
-                                (ins IGPR:$src),
-                                "; LDI8 PSEUDO",
-                                [(set i32:$dst, (sextloadi8 addr:$src))]>;
-
-def LDI16         : SHLoadPseudo<(outs GPR:$dst),
-                                (ins IGPR:$src),
-                                "; LDI16 PSEUDO",
-                                [(set i32:$dst, (sextloadi16 addr:$src))]>;
-
-def LDI32         : SHLoadPseudo<(outs GPR:$dst),
-                                (ins IGPR:$src),
-                                "; LDI32 PSEUDO",
-                                [(set i32:$dst, (load addr:$src))]>;
-
-def STI8         : SHStorePseudo<(outs),
-                                (ins GPR:$src, IGPR:$dst),
-                                "; STI8 PSEUDO",
-                                [(truncstorei8 i32:$src, addr:$dst)]>;
-
-def STI16        : SHStorePseudo<(outs),
-                                (ins GPR:$src, IGPR:$dst),
-                                "; STI16 PSEUDO",
-                                [(truncstorei16 i32:$src, addr:$dst)]>;
-
-def STI32        : SHStorePseudo<(outs),
-                                (ins GPR:$src, IGPR:$dst),
-                                "; STI32 PSEUDO",
-                                [(store i32:$src, addr:$dst)]>;
-
 //===--------------------------------------------------------------------------===//
 // SelectCC & SetCC
 //===--------------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 1c7ea011a5ed2..b861431ca934d 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -114,9 +114,9 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
 
     // mov r14,r1
     // add #-<frame size>,r1
-    BuildMI(MBB, MI, DebugLoc(), TII.get(SH::MOVRmRn), DstReg)
+    BuildMI(MBB, MI, DebugLoc(), TII.get(SH::MOV), DstReg)
       .addReg(SH::R14);
-    BuildMI(MBB, MI, DebugLoc(), TII.get(SH::ADDI8Rn), DstReg)
+    BuildMI(MBB, MI, DebugLoc(), TII.get(SH::ADDI), DstReg)
       .addReg(DstReg)
       .addImm(-StackSize);
 
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
index f44b472825f4c..f63c9e09670d5 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.td
@@ -146,8 +146,8 @@ let Namespace = "SH" in {
   // System Registers
   def PC    : SysReg<0, "pc">,    DwarfRegNum<[16]>;   // Program Counter
   def PR    : SysReg<0, "pr">,    DwarfRegNum<[17]>;   // Procedure Register
-  def MACH  : SysReg<1, "mach">,  DwarfRegNum<[20]>;   // Mult & Accum Hi
-  def MACL  : SysReg<0, "macl">,  DwarfRegNum<[21]>;   // Mult & Accum Low
+  def MACHI : SysReg<1, "mach">,  DwarfRegNum<[20]>;   // Mult & Accum Hi
+  def MACLO : SysReg<0, "macl">,  DwarfRegNum<[21]>;   // Mult & Accum Low
   def FPUL  : SysReg<0, "fpul">,  DwarfRegNum<[23]>;   // FPU Comms Register
   def FPSCR : SysReg<0, "fpscr">, DwarfRegNum<[24]>;   // FPU Status/Control Register
 
@@ -221,7 +221,7 @@ def CTRL : RegisterClass<"SH", [ i32 ], 32,
 
 // System registers.
 def SYS : RegisterClass<"SH", [ i32 ], 32, 
-  (add PR, PC, MACL, MACH, FPSCR, FPUL)>, Unallocatable;
+  (add PR, PC, MACLO, MACHI, FPSCR, FPUL)>, Unallocatable;
 
 // Program Counter
 def R_PC : RegisterClass<"SH", [ i32 ], 32, (add PC)>, Unallocatable;

>From e386f4ccf72eae6ab2cdfaeca2024348fb9fe423 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 4 Sep 2026 04:32:55 +0200
Subject: [PATCH 35/67] Refactor fixups

---
 .../SuperH/MCTargetDesc/SuperHAsmBackend.cpp  | 129 ++++++----------
 .../MCTargetDesc/SuperHELFObjectWriter.cpp    | 131 +++-------------
 .../SuperH/MCTargetDesc/SuperHFixupKinds.h    | 145 ++----------------
 .../MCTargetDesc/SuperHMCCodeEmitter.cpp      |  64 +++++---
 llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp   |  14 +-
 .../Target/SuperH/SuperHConstantPoolValue.cpp |   2 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  44 +++---
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp |   8 +-
 llvm/lib/Target/SuperH/SuperHMCInstLower.cpp  |  36 ++---
 9 files changed, 181 insertions(+), 392 deletions(-)

diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 71bdeb58cb7b3..5adcf90b23458 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -77,45 +77,13 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
       // SuperHFixupKinds.h.
       //
       // Name                    offset  bits  flags
-      {"fixup_got32",            0,      32,   0},
-      {"fixup_got_low16",        10,     16,   0},
-      {"fixup_got_medlow16",     10,     16,   0},
-      {"fixup_got_medhi16",      10,     16,   0},
-      {"fixup_got_hi16",         10,     16,   0},
-      {"fixup_got10by4",         10,     10,   0},
-      {"fixup_got10by8",         10,     10,   0},
-      {"fixup_plt32",            0,      32,   0},
-      {"fixup_plt_low16",        10,     16,   0},
-      {"fixup_plt_medlow16",     10,     16,   0},
-      {"fixup_plt_medhi16",      10,     16,   0},
-      {"fixup_plt_hi16",         10,     16,   0},
-      {"fixup_gotplt32",         0,      32,   0},
-      {"fixup_gotplt_low16",     10,     16,   0},
-      {"fixup_gotplt_medlow16",  10,     16,   0},
-      {"fixup_gotplt_medhi16",   10,     16,   0},
-      {"fixup_gotplt_hi16",      10,     16,   0},
-      {"fixup_gotoff",           0,      32,   0},
-      {"fixup_gotoff_low16",     10,     16,   0},
-      {"fixup_gotoff_medlow16",  10,     16,   0},
-      {"fixup_gotoff_medhi16",   10,     16,   0},
-      {"fixup_gotoff_hi16",      10,     16,   0},
-      {"fixup_gotpc",            0,      32,   0},
-      {"fixup_gotpc_low16" ,     10,     16,   0},
-      {"fixup_gotpc_medlow16" ,  10,     16,   0},
-      {"fixup_gotpc_medhi16" ,   10,     16,   0},
-      {"fixup_gotpc_hi16" ,      10,     16,   0},
-      {"fixup_copy",             0,      0,    0},
-      {"fixup_copy64",           0,      0,    0},
-      {"fixup_glob_dat",         0,      32,   0},
-      {"fixup_glob_dat64",       0,      64,   0},
-      {"fixup_jump_slot",        0,      32,   0},
-      {"fixup_jump_slot64",      0,      64,   0},
-      {"fixup_relative",         0,      32,   0},
-      {"fixup_relative64",       0,      64,   0},
-      {"fixup_dir32",            0,      32,   0},
-      {"fixup_rel32",            0,      32,   0},
-      {"fixup_64",               0,      64,   0},
-      {"fixup_64_pcrel",         0,      64,   0},
+      {"fixup_32",               0,      32,   0},
+      {"fixup_pcrel4_by2",       0,      16,   0},
+      {"fixup_pcrel4_by4",       0,      16,   0},
+      {"fixup_pcrel8_by4",       0,      16,   0},
+      {"fixup_pcrel8_4by2",      0,      16,   0},
+      {"fixup_pcrel8_4by4",      0,      16,   0},
+      {"fixup_pcrel12_4by2",     0,      16,   0},
   };
   // clang-format on
 
@@ -131,11 +99,6 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
   return Infos[Kind - FirstTargetFixupKind];
 }
 
-std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup &Fixup,
-                                                    MCValue &Target, uint64_t &FixedValue) {
-  return {};
-}
-
 unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
                                             const MCValue &Target, uint64_t Value,
                                             bool IsResolved, MCContext &Ctx,
@@ -147,55 +110,58 @@ unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixu
   default:
     return Value;
 
-  case FK_Data_2:
-  case FK_Data_4:
-    // NOTE:  Largest possible displacement is 12 bit, so force this.
-    return (Value & 0xFFF);
-
-  case SH::fixup_got_low16:
-    return (Value+Addend) & 65535;
-
-  case SH::fixup_got_medlow16:
-    return ((Value+Addend) >> 16) & 65535;
+  case SH::fixup_32:
+    return (Value+Addend) & 0xFFFFFFFF;
 
-  case SH::fixup_got_medhi16:
-    return ((Value+Addend) >> 32) & 65535;
+  case SH::fixup_pcrel4_by2:
+    return ((Value+Addend) / 2) & 0xF;
 
-  case SH::fixup_got_hi16:
-    return ((Value+Addend) >> 48) & 65535;
-
-  case SH::fixup_got10by4:
-    return (Value+Addend) / 4;
-
-  case SH::fixup_got10by8:
-    return (Value+Addend) / 8;
-
-  case SH::fixup_relative:
-  case SH::fixup_relative64:
-    return Value+Addend;
-
-  case SH::fixup_dir32:
-    return (Value+Addend);
-
-  case SH::fixup_rel32:
-    return Value+Addend;
+  case SH::fixup_pcrel4_by4:
+    return ((Value+Addend) / 4) & 0xF;
+  
+  case SH::fixup_pcrel8_by4:
+    return ((Value+Addend) / 4) & 0xFF;
+  
+  case SH::fixup_pcrel8_4by2:
+    return ((alignTo(Value, 2) + Addend - 4) / 2) & 0xFF;
+  
+  case SH::fixup_pcrel8_4by4:
+    return ((alignTo(Value, 4) + Addend - 4) / 4) & 0xFF;
+  
+  case SH::fixup_pcrel12_4by2:
+    return ((alignTo(Value, 2) + Addend - 4) / 2) & 0xFFF;
   }
 }
 
 bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
                                const MCValue &Target, uint64_t &FixedValue,
                                bool IsResolved) {
+  if (!IsResolved) {
+    Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
+    return false;
+  }
+  return true;
+}
+
+std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup &Fixup,
+                                                    MCValue &Target, uint64_t &FixedValue) {
   MCValue PCITarget; // PC-Indirect Target
 
   // Get indirect target location.
   switch(Fixup.getKind()) {
   default: 
-    return false;
+    return {};
 
   case FK_Data_1:
   case FK_Data_2:
   case FK_Data_4:
-  case FK_Data_8: {
+  case FK_Data_8: 
+  case SH::fixup_pcrel4_by2:
+  case SH::fixup_pcrel4_by4:
+  case SH::fixup_pcrel8_by4:
+  case SH::fixup_pcrel8_4by2:
+  case SH::fixup_pcrel8_4by4:
+  case SH::fixup_pcrel12_4by2: {
     const auto *EValue = Fixup.getValue();
     if (!EValue->evaluateAsRelocatable(PCITarget, Asm))
       return true;
@@ -213,20 +179,17 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
     return false;
 
   // Check if resolvable.
-  IsResolved = &SA.getSection() == F.getParent() &&
-                SA.getBinding() == ELF::STB_LOCAL &&
-                SA.getType() != ELF::STT_GNU_IFUNC;
-  if (!IsResolved) {
-    Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
+  bool IsResolved = &SA.getSection() == F.getParent() &&
+                     SA.getBinding() == ELF::STB_LOCAL &&
+                     SA.getType() != ELF::STT_GNU_IFUNC;
+  if (!IsResolved)
     return false;
-  }
 
   // Calculate fixed offset value.
   // Note that the PC relative jumps are based on the start of the address.
   // So it must be subtracted from the fixed value.
   FixedValue = Asm->getSymbolOffset(SA) + PCITarget.getConstant();
   FixedValue -= (Asm->getFragmentOffset(F) + Fixup.getOffset());
-  FixedValue /= 4; // Values are aligned to 4 bytes.
   return true;
 }
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index 292d55241e814..b7910e8bb2315 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -51,8 +51,8 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
   case FK_Data_1:
   case FK_Data_2:
   case FK_Data_8:
-    return 0;
-  
+    return ELF::R_SH_NONE;
+
   case FK_Data_4: {
     switch (Spec) {
     case SH::S_None:
@@ -60,121 +60,28 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
     case SH::S_PCREL:
       return ELF::R_SH_REL32;
     default:
-      return SH::S_DIR;
+      return ELF::R_SH_NONE;
+    }
+  }
+  
+  case SH::fixup_pcrel4_by2:
+  case SH::fixup_pcrel4_by4:
+  case SH::fixup_pcrel8_by4:
+  case SH::fixup_pcrel8_4by2:
+  case SH::fixup_pcrel12_4by2: {
+    switch (Spec) {
+    case SH::S_None:
+      return ELF::R_SH_DIR32;
+    case SH::S_PCREL:
+      return ELF::R_SH_REL32;
+    default:
+      return ELF::R_SH_NONE;
     }
   }
 
-  case SH::fixup_got32:
-    return ELF::R_SH_GOT32;
-
-  case SH::fixup_got_low16:
-    return ELF::R_SH_GOT_LOW16;
-
-  case SH::fixup_got_medlow16:
-    return ELF::R_SH_GOT_MEDLOW16;
-
-  case SH::fixup_got_medhi16:
-    return ELF::R_SH_GOT_MEDHI16;;
-
-  case SH::fixup_got_hi16:
-    return ELF::R_SH_GOT_HI16;
-
-  case SH::fixup_plt32:
-    return ELF::R_SH_PLT32;
-
-  case SH::fixup_plt_low16:
-    return ELF::R_SH_PLT_LOW16;
-
-  case SH::fixup_plt_medlow16:
-    return ELF::R_SH_PLT_MEDLOW16;
-
-  case SH::fixup_plt_medhi16:
-    return ELF::R_SH_PLT_MEDHI16;;
-
-  case SH::fixup_plt_hi16:
-    return ELF::R_SH_PLT_HI16;
-
-  case SH::fixup_gotplt32:
-    return ELF::R_SH_GOTPLT32;
-
-  case SH::fixup_gotplt_low16:
-    return ELF::R_SH_GOTPLT_LOW16;
-
-  case SH::fixup_gotplt_medlow16:
-    return ELF::R_SH_GOTPLT_MEDLOW16;
-
-  case SH::fixup_gotplt_medhi16:
-    return ELF::R_SH_GOTPLT_MEDHI16;;
-
-  case SH::fixup_gotplt_hi16:
-    return ELF::R_SH_GOTPLT_HI16;
-
-  case SH::fixup_gotoff:
-    return ELF::R_SH_GOTOFF;
-
-  case SH::fixup_gotoff_low16:
-    return ELF::R_SH_GOTOFF_LOW16;
-
-  case SH::fixup_gotoff_medlow16:
-    return ELF::R_SH_GOTOFF_MEDLOW16;
-
-  case SH::fixup_gotoff_medhi16:
-    return ELF::R_SH_GOTOFF_MEDHI16;;
-
-  case SH::fixup_gotoff_hi16:
-    return ELF::R_SH_GOTOFF_HI16;
-
-  case SH::fixup_gotpc:
-    return ELF::R_SH_GOTPC;
-
-  case SH::fixup_gotpc_low16:
-    return ELF::R_SH_GOTPC_LOW16;
-
-  case SH::fixup_gotpc_medlow16:
-    return ELF::R_SH_GOTPC_MEDLOW16;
-
-  case SH::fixup_gotpc_medhi16:
-    return ELF::R_SH_GOTPC_MEDHI16;;
-
-  case SH::fixup_gotpc_hi16:
-    return ELF::R_SH_GOTPC_HI16;
-
-  case SH::fixup_copy:
-    return ELF::R_SH_COPY;
-
-  case SH::fixup_copy64:
-    return ELF::R_SH_COPY64;
-
-  case SH::fixup_glob_dat:
-    return ELF::R_SH_GLOB_DAT;
-
-  case SH::fixup_glob_dat64:
-    return ELF::R_SH_GLOB_DAT64;
-
-  case SH::fixup_jump_slot:
-    return ELF::R_SH_JMP_SLOT;
-
-  case SH::fixup_jump_slot64:
-    return ELF::R_SH_JMP_SLOT64;
-
-  case SH::fixup_relative:
-    return ELF::R_SH_RELATIVE;
-
-  case SH::fixup_relative64:
-    return ELF::R_SH_RELATIVE64;
-
-  case SH::fixup_dir32:
+  case SH::fixup_32:
     return ELF::R_SH_DIR32;
 
-  case SH::fixup_rel32:
-    return ELF::R_SH_REL32;
-
-  case SH::fixup_64:
-    return ELF::R_SH_64;
-
-  case SH::fixup_64_pcrel:
-    return ELF::R_SH_64_PCREL;
-
   default:
     llvm_unreachable("invalid fixup kind!");
   }
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
index 821a588c3dd44..e965552f84ccd 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHFixupKinds.h
@@ -17,140 +17,29 @@ namespace SH {
 // clang-format off
 
 /// The set of supported fixups.
-///
-/// Although most of the current fixup types reflect a unique relocation
-/// one can have multiple fixup types for a given relocation and thus need
-/// to be uniquely named.
-///
-/// \note This table *must* be in the same order of
-///       MCFixupKindInfo Infos[SuperH::NumTargetFixupKinds]
-///       in `SuperHAsmBackend.cpp`.
 enum Fixups {
-  // The following fields follow the instructions in the C ABI Specification
-  // which can be found at https://www.renesas.com/en/document/mat/superh-cc-compiler-package-v904-users-manual?r=1169516
-  //
-  // NOTE:  Some relocation names are misspelled in the official manual,
-  //        The misspellings are corrected as follows:
-  //          - R_SH_PLT_MEWLOW16 -> R_SH_PLT_MEDLOW16
-  //
-  //  Name                Value          Field           Calculation
+  fixup_32 = FirstTargetFixupKind,
+  
+  /// A fixup that represents a PC-relative address scaled by 2.
+  fixup_pcrel4_by2,
 
-  // R_SH_GOT32           160            word32          G + A
-  fixup_got32 = FirstTargetFixupKind,
+  /// A fixup that represents a PC-relative address scaled by 4.
+  fixup_pcrel4_by4,
 
-  // R_SH_GOT_LOW16       169            T_32s10for16    (G + A) & 65535
-  fixup_got_low16,
+  /// A fixup that represents a PC-relative address scaled by 4.
+  fixup_pcrel8_by4,
 
-  // R_SH_GOT_MEDLOW16    170            T_32u10for16    ((G + A) >> 16) & 65535
-  fixup_got_medlow16,
+  /// A fixup that represents a PC-relative address scaled by 2,
+  /// with a 4-byte offset.
+  fixup_pcrel8_4by2,
 
-  // R_SH_GOT_MEDHI16     171            T_32u10for16    ((G + A) >> 32) & 65535
-  fixup_got_medhi16,
+  /// A fixup that represents a PC-relative address scaled by 4,
+  /// with a 4-byte offset.
+  fixup_pcrel8_4by4,
 
-  // R_SH_GOT_HI16        172            T_32u10for16    ((G + A) >> 48) & 65535
-  fixup_got_hi16,
-
-  // R_SH_GOT10BY4        189            V_32s10for10    (G + A) / 4
-  fixup_got10by4,
-
-  // R_SH_GOT10BY8        191            V_32s10for10    (G + A) / 8
-  fixup_got10by8,
-
-  // R_SH_PLT32           161            word32          L + A - P
-  fixup_plt32,
-
-  // R_SH_PLT_LOW16       177            T_32s10for16    (L + A - P) & 65535
-  fixup_plt_low16,
-
-  // R_SH_PLT_MEDLOW16    178            T_32u10for16    ((L + A - P) >> 16) & 65535
-  fixup_plt_medlow16,
-
-  // R_SH_PLT_MEDHI16     179            T_32u10for16    ((L + A - P) >> 32) & 65535
-  fixup_plt_medhi16,
-
-  // R_SH_PLT_HI16        180            T_32u10for16    ((L + A - P) >> 48) & 65535
-  fixup_plt_hi16,
-
-  // R_SH_GOTPLT32        168            word32          G + A
-  fixup_gotplt32,
-
-  // R_SH_GOTPLT_LOW16    169            T_32s10for16    (G + A) & 65535
-  fixup_gotplt_low16,
-
-  // R_SH_GOTPLT_MEDLOW16 170            T_32u10for16    ((G + A) >> 16) & 65535
-  fixup_gotplt_medlow16,
-
-  // R_SH_GOTPLT_MEDHI16  171            T_32u10for16    ((G + A) >> 32) & 65535
-  fixup_gotplt_medhi16,
-
-  // R_SH_GOTPLT_HI16     172            T_32u10for16    ((G + A) >> 48) & 65535
-  fixup_gotplt_hi16,
-
-  // R_SH_GOTOFF          166            word32          S + A - GOT
-  fixup_gotoff,
-
-  // R_SH_GOTOFF_LOW16    181            T_32s10for16    (S + A - GOT) & 65535
-  fixup_gotoff_low16,
-
-  // R_SH_GOTOFF_MEDLOW16 182            T_32u10for16    ((S + A - GOT) >> 16) & 65535
-  fixup_gotoff_medlow16,
-
-  // R_SH_GOTOFF_MEDHI16  183            T_32u10for16    ((S + A - GOT) >> 32) & 65535
-  fixup_gotoff_medhi16,
-
-  // R_SH_GOTOFF_HI16     184            T_32u10for16    ((S + A - GOT) >> 48) & 65535
-  fixup_gotoff_hi16,
-
-  // R_SH_GOTPC           167            word32          GOT + A - P
-  fixup_gotpc,
-
-  // R_SH_GOTPC_LOW16     185            T_32s10for16    (GOT + A - P) & 65535
-  fixup_gotpc_low16,
-
-  // R_SH_GOTPC_MEDLOW16  186            T_32u10for16    ((GOT + A - P) >> 16) & 65535
-  fixup_gotpc_medlow16,
-
-  // R_SH_GOTPC_MEDHI16   187            T_32u10for16    ((GOT + A - P) >> 32) & 65535
-  fixup_gotpc_medhi16,
-
-  // R_SH_GOTPC_HI16      188            T_32u10for16    ((GOT + A - P) >> 48) & 65535
-  fixup_gotpc_hi16,
-
-  // R_SH_COPY            162            none            none
-  fixup_copy,
-
-  // R_SH_COPY64          193            none            none
-  fixup_copy64,
-
-  // R_SH_GLOB_DAT        163            word32          S
-  fixup_glob_dat,
-
-  // R_SH_GLOB_DAT64      194            word64          S
-  fixup_glob_dat64,
-
-  // R_SH_JMP_SLOT        164            word32          S
-  fixup_jump_slot,
-
-  // R_SH_JMP_SLOT64      195            word64          S
-  fixup_jump_slot64,
-
-  // R_SH_RELATIVE        165            word32          B + A
-  fixup_relative,
-
-  // R_SH_RELATIVE64      196            word64          B + A
-  fixup_relative64,
-
-  // R_SH_DIR32           1              word32          S + A
-  fixup_dir32,
-
-  // R_SH_REL32           2              word32          S + A - P
-  fixup_rel32,
-
-  // R_SH_64              254            word64          S + A
-  fixup_64,
-
-  // R_SH_64_PCREL        255            word64          S + A - P
-  fixup_64_pcrel,
+  /// A fixup that represents a PC-relative address scaled by 2,
+  /// with a 4-byte offset.
+  fixup_pcrel12_4by2,
 
   // Marker
   LastTargetFixupKind,
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 690515d648564..1c8a76dcc7467 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -125,38 +125,58 @@ unsigned SuperHMCCodeEmitter::getOpBits(const MCInst &MI,
 // the given opcode.
 // This is neccesary due to the various opcodes that access memory
 // have different scaling factors applied.
-static std::optional<MCFixup> getFixupForOpcode(unsigned Opcode, const MCExpr *Expr, MCContext &Ctx) {
-  bool isOp32 = isOpcode32(Opcode) ? FK_Data_4 : FK_Data_2;
+static MCFixup getFixupForOpcode(unsigned Opcode, const MCExpr *Expr, MCContext &Ctx) {
+
+  // NOTE:  A few (DSP and SH2A) instructions are 32-bits wide.
+  //        We handle those quite crudely.
+  MCFixupKind Kind = isOpcode32(Opcode) ? FK_Data_4 : FK_Data_2;
 
   switch(Opcode) {
   default: break;
 
-  // disp * 2
-  case SH::BF:
-  case SH::BFS:
-  case SH::BT:
-  case SH::BTS:
-  case SH::BSR:
-  case SH::BRA:
-  case SH::MOVWI:
+  // disp4 * 2
   case SH::MOVWL4:
   case SH::MOVWLG:
   case SH::MOVWS4:
   case SH::MOVWSG:
-    Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(2, Ctx), Ctx);
+    Kind = SH::fixup_pcrel4_by2;
     break;
 
-  // disp * 4
-  case SH::MOVA:
-  case SH::MOVLI:
-  case SH::MOVLL4:
+  // disp4 * 4
   case SH::MOVLLG:
   case SH::MOVLS4:
   case SH::MOVLSG:
-    Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(4, Ctx), Ctx);
+    Kind = SH::fixup_pcrel4_by4;
+    break;
+
+  // disp8 * 4
+  case SH::MOVA:
+    Kind = SH::fixup_pcrel8_by4;
+    break;
+
+  // (disp8 * 2) + 4
+  case SH::BF:
+  case SH::BFS:
+  case SH::BT:
+  case SH::BTS:
+  case SH::MOVWI:
+  case SH::MOVLL4:
+    Kind = SH::fixup_pcrel8_4by2;
+    break;
+
+  // (disp8 * 4) + 4
+  case SH::MOVLI:
+    Kind = SH::fixup_pcrel8_4by4;
+    break;
+
+  // (disp12 * 2) + 4
+  case SH::BSR:
+  case SH::BRA:
+    Kind = SH::fixup_pcrel12_4by2;
     break;
   }
-  return MCFixup::create(0, Expr, isOp32 ? FK_Data_4 : FK_Data_2, true);
+
+  return MCFixup::create(0, Expr, Kind, true);
 }
 
 void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
@@ -199,9 +219,7 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
   if (!Expr)
     return 0;
 
-  MCExpr::ExprKind Kind = Expr->getKind();
-
-  switch(Kind) {
+  switch(Expr->getKind()) {
   case MCExpr::ExprKind::Binary: {
     unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI);
     Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI);
@@ -216,11 +234,7 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Exp
     return 0;
   }
   case MCExpr::ExprKind::SymbolRef: {
-
-    // NOTE:  A few (DSP and SH2A) instructions are 32-bits wide.
-    //        We handle those quite crudely.
-    uint32_t OpCode = getOpBits(MI, Fixups, STI);
-    Fixups.push_back(MCFixup::create(0, Expr, isOpcode32(OpCode) ? FK_Data_4 : FK_Data_2, true));
+    Fixups.push_back(getFixupForOpcode(MI.getOpcode(), Expr, Ctx));
     return 0;
   }
   case MCExpr::ExprKind::Constant: {
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index 567fcc79a3e0d..e6665581e722e 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -29,7 +29,7 @@
 
 using namespace llvm;
 
-#define DEBUG_TYPE "asm-printer"
+#define DEBUG_TYPE "sh-asm-printer"
 
 namespace {
 
@@ -84,6 +84,7 @@ class SuperHAsmPrinter : public AsmPrinter {
 } // namespace
 
 bool SuperHAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+  LLVM_DEBUG(dbgs() << "***** SuperHAsmPrinter *****\n");
   MCP = MF.getConstantPool();
   return AsmPrinter::runOnMachineFunction(MF);
 }
@@ -188,13 +189,24 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
     const BlockAddress *BA =
       cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
     MCSym = GetBlockAddressSymbol(BA);
+
+    dbgs() << "Emit CPV BlockAddress " << SCPV->getLabelId() 
+           << " \"" << MCSym->getName() << "\"...\n";
+
   } else if (SCPV->isGlobalValue()) {
     const GlobalValue *GV = cast<SuperHConstantPoolConstant>(SCPV)->getGV();
     MCSym = getSymbolPreferLocal(*GV);
+
+    dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() 
+           << " \"" << MCSym->getName() << "\"...\n";
+  
   } else {
     assert(SCPV->isExtSymbol() && "unrecognized constant pool value");
     auto Sym = cast<SuperHConstantPoolSymbol>(SCPV)->getSymbol();
     MCSym = GetExternalSymbolSymbol(Sym);
+
+    dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() 
+           << " \"" << MCSym->getName() << "\"...\n";
   }
 
   // Create an MCSymbol for the reference.
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
index cdedd3e8f634b..e102c2438a600 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
@@ -42,7 +42,7 @@ StringRef SuperHConstantPoolValue::getModifierText() const {
   case SHCP::GOT_PCREL:
     return "gotpcrel";
   case SHCP::DIR:
-    return "";
+    return "dir";
   }
   llvm_unreachable("Unknown modifier!");
 }
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index ca9b1bebcabb5..f89a607502340 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -143,8 +143,6 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
   auto DL = CurDAG->getDataLayout();
   MVT PtrVT = getTargetLowering()->getPointerTy(DL);
 
-  LLVM_DEBUG(dbgs() << "SelectAddr\n");
-
   // if the address is a frame index get the TargetFrameIndex.
   if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
@@ -170,28 +168,34 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
   SDValue N0 = N->getOperand(0);
 
-  // External Symbols
-  if (auto *CPV = SFI->tryGetConstant((ExternalSymbolSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
-    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
-    ReplaceNode(N, Res);
-    return true;
-  }
-
   // Global Addresses
-  if (auto *CPV = SFI->tryGetConstant((GlobalAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
-    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
-    ReplaceNode(N, Res);
-    return true;
+  if (GlobalAddressSDNode* GA = dyn_cast<GlobalAddressSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(GA, *CurDAG, SHCP::no_modifier)) {
+      SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+      MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
+      ReplaceNode(N, Res);
+      return true;
+    }
   }
 
   // Block Addresses
-  if (auto *CPV = SFI->tryGetConstant((BlockAddressSDNode*)N0.getNode(), *CurDAG, SHCP::no_modifier)) {
-    SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
-    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
-    ReplaceNode(N, Res);
-    return true;
+  if (BlockAddressSDNode* BA = dyn_cast<BlockAddressSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(BA, *CurDAG, SHCP::no_modifier)) {
+      SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+      MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
+      ReplaceNode(N, Res);
+      return true;
+    }
+  }
+
+  // External Symbols
+  if (ExternalSymbolSDNode* Sym = dyn_cast<ExternalSymbolSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(Sym, *CurDAG, SHCP::no_modifier)) {
+      SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+      MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
+      ReplaceNode(N, Res);
+      return true;
+    }
   }
 
   return false;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 78a63370a645e..6ea55fc313a75 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -200,8 +200,8 @@ SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
     auto PtrVT = getPointerTy(DAG.getDataLayout());
     auto DL = SDLoc(G);
 
-    // SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
-    SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0);
+    SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
+    SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, OpFlags);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
   }
   return SDValue();
@@ -218,7 +218,7 @@ SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG)
     const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
     SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
 
-    SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT);
+    SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
   }
   return SDValue();
@@ -235,7 +235,7 @@ SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) c
     const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
     SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
 
-    SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT);
+    SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT, 0, OpFlags);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
   }
   return SDValue();
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index 157e06680e986..79451cd815e4a 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -22,29 +22,29 @@ SuperHMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
                                       const SuperHSubtarget &Subtarget) const {
   const MCExpr *Expr = nullptr;
   switch (MO.getTargetFlags()) {
-    case SHII::MO_NO_FLAG:
-      Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
-      break;
+  case SHII::MO_NO_FLAG:
+    Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
+    break;
 
-    case SHII::MO_GOT:
-      Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT, Ctx);
-      break;
+  case SHII::MO_GOT:
+    Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT, Ctx);
+    break;
 
-    case SHII::MO_GOTPC:
-      Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_PCREL, Ctx);
-      break;
+  case SHII::MO_GOTPC:
+    Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_PCREL, Ctx);
+    break;
 
-    case SHII::MO_GOTOFF:
-      Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_OFF, Ctx);
-      break;
+  case SHII::MO_GOTOFF:
+    Expr = MCSymbolRefExpr::create(Sym, SH::S_GOT_OFF, Ctx);
+    break;
 
-    case SHII::MO_DIR:
-      Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
-      break;
+  case SHII::MO_DIR:
+    Expr = MCSymbolRefExpr::create(Sym, SH::S_DIR, Ctx);
+    break;
 
-    case SHII::MO_PCREL:
-      Expr = MCSymbolRefExpr::create(Sym, SH::S_PCREL, Ctx);
-      break;
+  case SHII::MO_PCREL:
+    Expr = MCSymbolRefExpr::create(Sym, SH::S_PCREL, Ctx);
+    break;
   }
   return MCOperand::createExpr(Expr);
 }

>From e9bc64403b8c30c3075ba8e4d200034bceaf348e Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 4 Sep 2026 04:33:48 +0200
Subject: [PATCH 36/67] Fix frame index elimination, add more clang scaffolding

---
 clang/lib/CodeGen/CMakeLists.txt              |   1 +
 clang/lib/CodeGen/CodeGenModule.cpp           |   5 +
 clang/lib/CodeGen/TargetInfo.h                |   3 +
 clang/lib/CodeGen/Targets/SuperH.cpp          |  93 +++++++++++
 llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp   |  12 +-
 .../lib/Target/SuperH/SuperHFrameLowering.cpp |  99 +++++++-----
 llvm/lib/Target/SuperH/SuperHFrameLowering.h  |  15 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |   5 +-
 .../Target/SuperH/SuperHMachineFunctionInfo.h |   3 +
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 148 +++++++++++++++---
 .../lib/Target/SuperH/SuperHTargetMachine.cpp |   1 -
 llvm/lib/TargetParser/TargetDataLayout.cpp    |   4 +-
 12 files changed, 310 insertions(+), 79 deletions(-)
 create mode 100644 clang/lib/CodeGen/Targets/SuperH.cpp

diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index d3986ddecfe12..b6fc9d3957264 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -154,6 +154,7 @@ add_clang_library(clangCodeGen
   Targets/RISCV.cpp
   Targets/SPIR.cpp
   Targets/Sparc.cpp
+  Targets/SuperH.cpp
   Targets/SystemZ.cpp
   Targets/TCE.cpp
   Targets/VE.cpp
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 7bb0e9d8ff560..f0b95456ca025 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -246,6 +246,11 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
     bool EABI = ABIStr.ends_with("e");
     return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
   }
+  
+  case llvm::Triple::sh:
+  case llvm::Triple::shl: {
+    return createSuperHTargetCodeGenInfo(CGM);
+  }
 
   case llvm::Triple::systemz: {
     bool SoftFloat = CodeGenOpts.FloatABI == "soft";
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index fae32068b1570..5ee1c6c37bfcf 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -602,6 +602,9 @@ createSparcV8TargetCodeGenInfo(CodeGenModule &CGM);
 std::unique_ptr<TargetCodeGenInfo>
 createSparcV9TargetCodeGenInfo(CodeGenModule &CGM);
 
+std::unique_ptr<TargetCodeGenInfo>
+createSuperHTargetCodeGenInfo(CodeGenModule &CGM);
+
 std::unique_ptr<TargetCodeGenInfo>
 createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector,
                                bool SoftFloatABI);
diff --git a/clang/lib/CodeGen/Targets/SuperH.cpp b/clang/lib/CodeGen/Targets/SuperH.cpp
new file mode 100644
index 0000000000000..eae3cd39de190
--- /dev/null
+++ b/clang/lib/CodeGen/Targets/SuperH.cpp
@@ -0,0 +1,93 @@
+//===- SuperH.cpp ---------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABIInfoImpl.h"
+#include "TargetInfo.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/Support/MathExtras.h"
+
+using namespace clang;
+using namespace clang::CodeGen;
+
+//===----------------------------------------------------------------------===//
+// SuperH ABI Implementation. Documented at
+// https://llvm-gcc-renesas.com/manuals/SH-ABI-Specification.html
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SuperHABIInfo : public DefaultABIInfo {
+public:
+  SuperHABIInfo(CodeGenTypes &CGT)
+      : DefaultABIInfo(CGT) {}
+
+  ABIArgInfo classifyReturnType(QualType Ty, bool &LargeRet) const {
+
+    // We have a total of 64 bits of return space in R0 and R1,
+    // if we can fit a struct in there, do.
+    if (isAggregateTypeForABI(Ty) && 
+        getContext().getTypeSize(Ty) <= 64)
+      return ABIArgInfo::getDirect();
+
+    // Otherwise, we store a pointer to the struct in R2 and return that.
+    if (getContext().getTypeSize(Ty) > 64) {
+      LargeRet = true;
+      return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+    }
+
+    // Otherwise we follow the default way which is compatible.
+    return DefaultABIInfo::classifyReturnType(Ty);
+  }
+
+  ABIArgInfo classifyArgumentType(QualType Ty, unsigned &NumRegs) const {
+    unsigned TySize = getContext().getTypeSize(Ty);
+
+    // Smaller types are required to be sign extended.
+    if (TySize < 32 && NumRegs > 0 && Ty->isIntegralOrEnumerationType()) {
+      NumRegs -= 1;
+      return ABIArgInfo::getExtend(Ty);
+    }
+
+    // If there's enough space, pass in registers.
+    if (TySize <= NumRegs * 32) {
+      NumRegs -= TySize / 32;
+      return ABIArgInfo::getDirect();
+    }
+
+    // A pointer will be created and passsed in R4 instead, as the arguments
+    // from here on out doesn't fit in the remaining registers.
+    NumRegs = 0;
+    return ABIArgInfo::getDirect();
+  }
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+
+    // Decide the return type.
+    bool LargeRet = false;
+    if (!getCXXABI().classifyReturnType(FI))
+      FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), LargeRet);
+    
+    // Decide each argument type.
+    unsigned NumRegs = 4;
+    for (auto &I : FI.arguments())
+      I.info = classifyArgumentType(I.type, NumRegs);
+  }
+
+};
+
+class SuperHTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  SuperHTargetCodeGenInfo(CodeGenTypes &CGT)
+      : TargetCodeGenInfo(std::make_unique<SuperHABIInfo>(CGT)) {}
+
+};
+}
+
+std::unique_ptr<TargetCodeGenInfo>
+CodeGen::createSuperHTargetCodeGenInfo(CodeGenModule &CGM) {
+  return std::make_unique<SuperHTargetCodeGenInfo>(CGM.getTypes());
+}
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index e6665581e722e..0baa06d54cfa7 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -190,23 +190,23 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
       cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
     MCSym = GetBlockAddressSymbol(BA);
 
-    dbgs() << "Emit CPV BlockAddress " << SCPV->getLabelId() 
-           << " \"" << MCSym->getName() << "\"...\n";
+    LLVM_DEBUG(dbgs() << "Emit CPV BlockAddress " << SCPV->getLabelId() 
+                      << " \"" << MCSym->getName() << "\"...\n");
 
   } else if (SCPV->isGlobalValue()) {
     const GlobalValue *GV = cast<SuperHConstantPoolConstant>(SCPV)->getGV();
     MCSym = getSymbolPreferLocal(*GV);
 
-    dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() 
-           << " \"" << MCSym->getName() << "\"...\n";
+    LLVM_DEBUG(dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() 
+                      << " \"" << MCSym->getName() << "\"...\n");
   
   } else {
     assert(SCPV->isExtSymbol() && "unrecognized constant pool value");
     auto Sym = cast<SuperHConstantPoolSymbol>(SCPV)->getSymbol();
     MCSym = GetExternalSymbolSymbol(Sym);
 
-    dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() 
-           << " \"" << MCSym->getName() << "\"...\n";
+    LLVM_DEBUG(dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() 
+                      << " \"" << MCSym->getName() << "\"...\n");
   }
 
   // Create an MCSymbol for the reference.
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 5b3bd8840f0c7..32106d529a021 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -25,6 +25,7 @@
 #include "llvm/MC/MCRegister.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/DebugLog.h"
+#include "llvm/Support/TypeSize.h"
 #include "llvm/Target/TargetMachine.h"
 #include <cstdint>
 
@@ -130,49 +131,53 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
   const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
   const MCContext &Ctx = MF.getContext();
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
+  bool HasFP = hasFP(MF);
 
   Register SP = RII.getStackRegister();
   Register FP = RII.getFrameRegister();
   Register GOT = RII.getGOTRegister();
 
-  LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
+  // Reference register.
+  Register Ref = HasFP ? SP : FP;
 
-  // Early exit if we have no frame pointer.
-  if (!hasFP(MF)) {
-    return;
-  }
+  LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
 
   // Realign stack to 32-bit offsets.
   uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
   MFI.setStackSize(StackSize);
-  
-  // Store GOT
-  if (STI.isPositionIndependent()) {
-    if (auto *GOTSym = MF.getPICBaseSymbol()) {
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
-        .addReg(GOT)
-        .setMIFlag(MachineInstr::FrameSetup);
-    }
-  }
 
-  // Establish Stack Frame
-  //    mov.l r14, at -r15
-  //    add <stackadj>,r15
-  //    mov r15,r14
-  BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
-    .addReg(FP)
-    .setMIFlag(MachineInstr::FrameSetup);
-  emitSPAdj(MF, MBB, MBBI, -(int32_t)StackSize);
-  BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
-    .addReg(SP)
-    .setMIFlag(MachineInstr::FrameSetup);
+  // Store previous frame pointer.
+  if (HasFP) {
+    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), FP)
+      .addReg(SP)
+      .setMIFlag(MachineInstr::FrameSetup);
+  }
 
-  // Save return address to stack.
+  // Store Return address on stack (if needed)
   if (MFI.hasCalls()) {
     BuildMI(MBB, MBBI, DL, TII.get(SH::STSMPR))
       .addReg(SP)
       .setMIFlag(MachineInstr::FrameSetup);
+    BuildMI(MBB, MBBI, DL, TII.get(SH::ADDI), SP)
+      .addReg(SP)
+      .addImm(-4);
   }
+
+  // Create new frame pointer.
+  if (HasFP) {
+    BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
+      .addReg(SP)
+      .setMIFlag(MachineInstr::FrameSetup);
+  }
+
+  // // Store GOT
+  // if (STI.isPositionIndependent()) {
+  //   if (auto *GOTSym = MF.getPICBaseSymbol()) {
+  //     BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
+  //       .addReg(GOT)
+  //       .setMIFlag(MachineInstr::FrameSetup);
+  //   }
+  // }
 }
 
 void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
@@ -239,6 +244,13 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
     }
   }
 }
+
+void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
+                        RegScavenger *RS) const {
+  LLVM_DEBUG(dbgs() << "determineCalleeSaves\n");
+  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
+}
+
 bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
                                  ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
   
@@ -260,7 +272,6 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
       .addReg(Reg)
       .setMIFlag(MachineInstr::FrameSetup);
   }
-
   return true;
 }
 
@@ -279,7 +290,6 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
   const TargetInstrInfo &TII = *STI.getInstrInfo();
   Register SP = RII.getStackRegister();
 
-
   for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
 
     MCRegister Reg = I.getReg();
@@ -291,6 +301,25 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
   return true;
 }
 
+StackOffset
+SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
+                                           Register &FrameReg) const {
+  const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
+  const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
+  bool HasFP = hasFP(MF);
+
+  // R14 base
+  int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
+  if (HasFP) {
+    FrameReg = RegInfo->getFrameRegister();
+    return StackOffset::getFixed(FrameOffset);
+  }
+
+  // R15 base
+  FrameReg = RegInfo->getStackRegister(); // %sp
+  return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());
+}
+
 MachineBasicBlock::iterator
 SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF, 
                             MachineBasicBlock &MBB,
@@ -308,15 +337,6 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
   if (Amount == 0) {
     return MBB.erase(MI);
   }
-
-  DebugLoc DL = MI->getDebugLoc();
-  unsigned int Opcode = MI->getOpcode();
-  if (Opcode == TII.getCallFrameSetupOpcode()) {
-
-  } else {
-    assert(Opcode == TII.getCallFrameDestroyOpcode());
-  }
-
   return MBB.erase(MI);
 }
 
@@ -336,9 +356,4 @@ bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
 bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   return hasFP(MF) && !MFI.hasVarSizedObjects();
-}
-
-void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
-                        RegScavenger *RS) const {
-  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index 66c3ff6eb6dce..0f8bc43b4f4ce 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -29,7 +29,7 @@ class SuperHFrameLowering : public TargetFrameLowering {
     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
                           /*StackAlignment*/Align(4),
                           /*LocalAreaOffset*/0,
-                          /*TransAl*/Align(4),
+                          /*TransAl*/Align(1),
                           /*StackReal*/false),
       STI(STI) {}
   bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
@@ -41,13 +41,20 @@ class SuperHFrameLowering : public TargetFrameLowering {
                                  ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
   bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
                                    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
+
+  void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
+                            RegScavenger *RS) const override;
   
+
+  /// getFrameIndexReference - This method should return the base register
+  /// and offset used to reference a frame index location. The offset is
+  /// returned directly, and the base register is returned via FrameReg.
+  StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
+                                     Register &FrameReg) const override;
+
   MachineBasicBlock::iterator
   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
                                 MachineBasicBlock::iterator I) const override;
-
-  void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
-                            RegScavenger *RS) const override;
 protected:
   bool hasFPImpl(const MachineFunction &MF) const override;
 };
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index e65d05a4c2276..35447696b9a20 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -126,7 +126,6 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                            Register DestReg, Register SrcReg, bool KillSrc,
                            bool RenamableDest,
                            bool RenamableSrc) const {
-
   // Do nothing, self copy.
   if (SrcReg == DestReg)
     return;
@@ -259,6 +258,8 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
 }
 
 Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+  LLVM_DEBUG(dbgs() << "isLoadFromStackSlot\n");
+
   if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
       MI.getOperand(2).getImm() == 0) {
     FrameIndex = MI.getOperand(1).getIndex();
@@ -268,6 +269,8 @@ Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &Frame
 }
 
 Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+  LLVM_DEBUG(dbgs() << "isStoreToStackSlot\n");
+
   if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
       MI.getOperand(1).getImm() == 0) {
     FrameIndex = MI.getOperand(0).getIndex();
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
index 33264e71670a0..c330e0b4ec931 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -15,6 +15,7 @@
 #define LLVM_LIB_TARGET_SUPERH_SUPERHMACHINEFUNCTION_H
 
 #include "SuperHConstantPoolValue.h"
+#include "llvm/ADT/BitVector.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/Register.h"
@@ -28,6 +29,8 @@ class SuperHMachineFunctionInfo : public MachineFunctionInfo {
   /// CPIndexCount - How many constant pool indices are allocated. 
   unsigned CPIndexCount = 0;
 
+  BitVector UsedRegs;
+
 public:
   explicit SuperHMachineFunctionInfo(const Function &F,
                                      const TargetSubtargetInfo *STI) {}
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index b861431ca934d..75f42e2b29467 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -19,6 +19,8 @@
 #include "SuperH.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/Support/Debug.h"
 
@@ -85,12 +87,40 @@ BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   return Reserved;
 }
 
+/// getLoadBaseOffset - Gets the base offset to emit a load/store from.
+static int64_t getLoadStoreBaseOffset(unsigned Opcode) {
+  switch(Opcode) {
+  case SH::MOVBL4:
+  case SH::MOVBS4:
+    return 12;
+
+  case SH::MOVWL4:
+  case SH::MOVWS4:
+    return 28;
+
+  case SH::MOVLS4:
+  case SH::MOVLL4:
+    return 60;
+
+  default:
+    return 0;
+  }
+}
+
+static void replaceFI(const MachineFunction &MF, MachineBasicBlock::iterator II,
+                      MachineInstr &MI, const DebugLoc &dl,
+                      unsigned FIOperandNum, int Offset, Register FramePtr) {
+
+  MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
+  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
+}
+
 bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
                                            int SPAdj,
                                            unsigned FIOperandNum,
                                            RegScavenger *RS) const {
   MachineInstr &MI = *II;
-  DebugLoc dl = MI.getDebugLoc();
+  DebugLoc DL = MI.getDebugLoc();
   MachineBasicBlock &MBB = *MI.getParent();
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -99,33 +129,105 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   const TargetInstrInfo &TII = *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
 
-  int64_t Size = MFI.getObjectSize(FrameIndex);
-  int64_t StackSize = MFI.getStackSize() + 8;
-  int64_t Offset = MFI.getObjectOffset(FrameIndex);
-  
-  // Add 4 to offset because SP points to saved FP
-  Offset += StackSize - TFI->getOffsetOfLocalArea() + 4;
-
-  // Fold incoming offset.
-  Offset += MI.getOperand(FIOperandNum + 1).getImm();
+  dbgs() << FrameIndex << " " << TII.getName(MI.getDesc().getOpcode()) << "\n";
+
+  // Get the register offset to fetch.
+  Register FrameReg;
+  int64_t Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
+  Offset += MFI.getStackSize();
+
+  int64_t ROff = getLoadStoreBaseOffset(MI.getOpcode());
+
+  // Handle frame loads and stores.
+  switch(MI.getOpcode()) {
+
+  // Stack Store
+  case SH::MOVBS4:
+  case SH::MOVWS4: {
+    Register SrcReg = MI.getOperand(0).getReg();
+
+    MI.dump();
+    dbgs() << "\n";
+    
+    // Expand sequence to
+    // mov      <base reg>,r1
+    // add      #-ROff,r1
+    // mov      <src reg>, r0
+    // mov.w/b  r0,@(ROff+Offset,r1)
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
+      .addReg(FrameReg);
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
+      .addReg(SH::R1)
+      .addImm(-ROff);
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R0)
+      .addReg(SrcReg);
+
+    Offset = ROff+Offset;
+    FrameReg = SH::R1;
+    break;
+  }
+  case SH::MOVLS4: {
+
+    MI.dump();
+    dbgs() << "\n";
+    
+    // Expand sequence to
+    // mov      <base reg>,r1
+    // add      #-ROff,r1
+    // mov.l    <src reg>,@(ROff+Offset,r1)
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
+      .addReg(FrameReg);
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
+      .addReg(SH::R1)
+      .addImm(-ROff);
+    Offset = ROff+Offset;
+    FrameReg = SH::R1;
+    break;
+  }
 
-  if (MI.getOpcode() == SH::SHFrmIdx) {
+  // Stack Load
+  case SH::MOVBL4:
+  case SH::MOVWL4: {
     Register DstReg = MI.getOperand(0).getReg();
 
-    // mov r14,r1
-    // add #-<frame size>,r1
-    BuildMI(MBB, MI, DebugLoc(), TII.get(SH::MOV), DstReg)
-      .addReg(SH::R14);
-    BuildMI(MBB, MI, DebugLoc(), TII.get(SH::ADDI), DstReg)
-      .addReg(DstReg)
-      .addImm(-StackSize);
-
-    II++;
-    MI.eraseFromParent();
+    // Expand sequence to
+    // mov      <base reg>,r1
+    // add      #-ROff,r1
+    // mov.w/b  @(ROff+Offset,r1),r0
+    // mov      r0,<dst reg>
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
+      .addReg(FrameReg);
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
+      .addReg(SH::R1)
+      .addImm(-ROff);
+
+    // This inserts it after our instruction
+    BuildMI(*MI.getParent(), MI, DL, TII.get(SH::ADDI), DstReg)
+      .addReg(SH::R0)
+      .addImm(-ROff);
+
+    Offset = ROff+Offset;
+    FrameReg = SH::R1;
+    break;
+  }
+  case SH::MOVLL4: {
+
+    // Expand sequence to
+    // mov    <base reg>,r1
+    // add    #-ROff,r1
+    // mov.l  @(ROff+Offset,r1),<dst reg>
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
+      .addReg(FrameReg);
+    BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
+      .addReg(SH::R1)
+      .addImm(-ROff);
+    Offset = ROff+Offset;
+    FrameReg = SH::R1;
+    break;
+  }
   }
 
-  MI.getOperand(FIOperandNum).ChangeToRegister(SH::R1, false);
-  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
+  replaceFI(MF, II, MI, DL, FIOperandNum, Offset, FrameReg);
   return false;
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 86a4a4c41bd85..c39f3d643d94f 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -96,7 +96,6 @@ SuperHTargetMachine::SuperHTargetMachine(const Target &T, const Triple &TT,
                                RM.value_or(Reloc::Static),
                                getEffectiveCodeModel(CM, CodeModel::Small),
                                OL), TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
-
   initAsmInfo();
 }
 
diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp
index 2321190fa50be..901ea8b892f91 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -567,10 +567,10 @@ static std::string computeVEDataLayout(const Triple &T) {
 static std::string computeSuperHDataLayout(const Triple &T) {
 
   // Mixed-endian
-  std::string Ret = T.getArch() == Triple::shl ? "e" : "E";
+  std::string Ret = T.isLittleEndian() ? "e" : "E";
 
   // ELF name manging
-  Ret += "-m:e";
+  Ret += getManglingComponent(T);
 
   // 32-bit pointers, 32 bit aligned
   Ret += "-p:32:32";

>From e81074e8fd7caf166e708de1d1f06438f74cda05 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 4 Sep 2026 07:37:50 +0200
Subject: [PATCH 37/67] Fix stack-frame & frame-index lowering

---
 .../lib/Target/SuperH/SuperHFrameLowering.cpp | 242 +++++++++---------
 llvm/lib/Target/SuperH/SuperHFrameLowering.h  |   2 +
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp |  42 ++-
 3 files changed, 154 insertions(+), 132 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 32106d529a021..fe6003e7244ae 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -25,6 +25,7 @@
 #include "llvm/MC/MCRegister.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/DebugLog.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/TypeSize.h"
 #include "llvm/Target/TargetMachine.h"
 #include <cstdint>
@@ -37,6 +38,13 @@ AccumOutgoingArgs("sh-accumulate-outgoing-args", cl::Hidden, cl::init(false),
 
 using namespace llvm;
 
+
+
+
+//===--------------------------------------------------------------------------===//
+//                                    Helpers
+//===--------------------------------------------------------------------------===//
+
 // Get amount of times to shift the value in a SP adjustment
 // for it to fit.
 static unsigned getShiftAmt(uint32_t Val) {
@@ -48,50 +56,42 @@ static unsigned getShiftAmt(uint32_t Val) {
   return R;
 }
 
+/// adjustFrameOffsetDown - Helper that adjusts frame offset
+/// down. 
+static void adjustFrameOffsetDown(int64_t &FrameOffset) {
+  FrameOffset -= 4;
+  if (FrameOffset < 0)
+    FrameOffset = 0;
+}
+
 // Helper to emit stack pointer adjustment.
-static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasicBlock::iterator MBBI, int32_t AdjValue) {
-  DebugLoc dl;
+void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB, 
+                                          MachineBasicBlock::iterator MBBI, int32_t AdjValue) const {
   const SuperHInstrInfo &TII = *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
-  const SuperHRegisterInfo &RII = *static_cast<const SuperHRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
   MachineInstr::MIFlag MFlag = AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
+  DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
   
   // No stack frame allocation neccesary.
   if (AdjValue == 0)
-    return false;
-
-  Register SP = RII.getStackRegister();
-  Register FP = RII.getFrameRegister();
-
-  if (abs(AdjValue) < 255) {
-
-    if (AdjValue < 0) {
-
-      // Fast path, emit a single immediate add.
-      //    Emit add #-(size),r15
-      BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI), SP)
-        .addReg(SP)
-        .addImm((int)AdjValue);
-      return true;
-    }
-
-    if (AdjValue > 0) {
+    return;
 
-      // Fast path, emit a single immediate add.
-      //    Emit add #(size),r14
-      BuildMI(MBB, MBBI, dl, TII.get(SH::ADDI), FP)
-        .addReg(FP)
-        .addImm((int)AdjValue);
-      return true;
-    }
+  // Check if the adjustment can fit in an 8-bit immediate.
+  if (isInt<8>(AdjValue)) {
 
+    // Fast path, emit a single immediate add.
+    BuildMI(MBB, MBBI, DL, TII.get(SH::ADDI), Base)
+      .addReg(Base)
+      .addImm(AdjValue);
+    return;
   }
 
+  // TODO: Embed a constant instead?
+
   // Slow path, shift 8 bits at a time into r0.
   unsigned ToShift = getShiftAmt(AdjValue);
 
   // Empty R0 in case it had something.
-  BuildMI(MBB, MBBI, dl, TII.get(SH::MOVI), SH::R0)
-    .addImm(0)
+  BuildMI(MBB, MBBI, DL, TII.get(SH::XOR), SH::R0)
     .addReg(SH::R0)
     .setMIFlag(MFlag);
 
@@ -99,52 +99,85 @@ static bool emitSPAdj(MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasic
   //  or #(byte), r0
   //  shll8 r0
   for(unsigned i = 0; i < ToShift; i++) {
-    BuildMI(MBB, MBBI, dl, TII.get(SH::ORI))
+    BuildMI(MBB, MBBI, DL, TII.get(SH::ORI))
       .addImm((AdjValue >> (i*8)) & 0xFF)
       .setMIFlag(MFlag);
-    BuildMI(MBB, MBBI, dl, TII.get(SH::SHLL8), SH::R0)
+    BuildMI(MBB, MBBI, DL, TII.get(SH::SHLL8), SH::R0)
       .addReg(SH::R0)
       .setMIFlag(MFlag);
   }
 
   // Finally negate and add to r15.
   //  neg r0, r0 (if negative displacement)
-  //  add r0, r15
+  //  add r0, <base>
   if (AdjValue < 0)
-    BuildMI(MBB, MBBI, dl, TII.get(SH::NEG), SH::R0)
+    BuildMI(MBB, MBBI, DL, TII.get(SH::NEG), SH::R0)
       .addReg(SH::R0)
       .addReg(SH::R0)
       .setMIFlag(MFlag);
 
-  BuildMI(MBB, MBBI, dl, TII.get(SH::SUB), SP)
+  BuildMI(MBB, MBBI, DL, TII.get(SH::SUB), Base)
     .addReg(SH::R0, RegState::Kill)
-    .addReg(SP)
+    .addReg(Base)
     .setMIFlag(MFlag);
-  return true;
 }
 
+StackOffset
+SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
+                                           Register &FrameReg) const {
+  const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
+  const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
+  bool HasFP = hasFP(MF);
+
+  // NOTE:  All the frame indices are relative to the stack/frame pointer
+  //        post-offset. as such an extra adjustment is needed here.
+  int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
+  FrameOffset += MFI.getStackSize() - TFI->getOffsetOfLocalArea();
+  
+  // Adjust down to remove SP.
+  adjustFrameOffsetDown(FrameOffset);
+
+  // R14 base
+  if (HasFP) {
+
+    // Adjust down to remove FP.
+    adjustFrameOffsetDown(FrameOffset);
+    FrameReg = RegInfo->getFrameRegister();
+    return StackOffset::getFixed(FrameOffset);
+  }
+
+  // R15 base
+  FrameReg = RegInfo->getStackRegister(); // r15
+  return StackOffset::getFixed(FrameOffset);
+}
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//                          Prologue/Epilogue Emission
+//===--------------------------------------------------------------------------===//
+
 void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+  LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
+
   MachineBasicBlock::iterator MBBI = MBB.begin();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   const SuperHInstrInfo &TII = *STI.getInstrInfo();
   const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
   const MCContext &Ctx = MF.getContext();
-  DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
-  bool HasFP = hasFP(MF);
-
   Register SP = RII.getStackRegister();
   Register FP = RII.getFrameRegister();
   Register GOT = RII.getGOTRegister();
+  DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
+  bool HasFP = hasFP(MF);
 
-  // Reference register.
-  Register Ref = HasFP ? SP : FP;
-
-  LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
-
-  // Realign stack to 32-bit offsets.
-  uint32_t StackSize = alignSPAdjust(MFI.getStackSize());
-  MFI.setStackSize(StackSize);
+  // Get stack frame size.
+  int64_t StackSize = MFI.getStackSize();
+  adjustFrameOffsetDown(StackSize);
 
   // Store previous frame pointer.
   if (HasFP) {
@@ -158,12 +191,10 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
     BuildMI(MBB, MBBI, DL, TII.get(SH::STSMPR))
       .addReg(SP)
       .setMIFlag(MachineInstr::FrameSetup);
-    BuildMI(MBB, MBBI, DL, TII.get(SH::ADDI), SP)
-      .addReg(SP)
-      .addImm(-4);
   }
 
-  // Create new frame pointer.
+  // Create new stack frame.
+  emitFrameAdjust(SP, MF, MBB, MBBI, -StackSize);
   if (HasFP) {
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
       .addReg(SP)
@@ -181,69 +212,55 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
 }
 
 void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+  LLVM_DEBUG(dbgs() << "Emitting epilogue...\n");
+
+  MachineBasicBlock::iterator MBBI = MBB.begin();
   const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
+  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+  const SuperHInstrInfo &TII = *STI.getInstrInfo();
+  MachineFrameInfo &MFI = MF.getFrameInfo();
   Register SP = RII.getStackRegister();
   Register FP = RII.getFrameRegister();
+  DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
+  bool HasFP = hasFP(MF);
 
-  LLVM_DEBUG(dbgs() << "Emitting epilogue...\n");
+  // Get stack frame size.
+  int64_t StackSize = MFI.getStackSize();
+  adjustFrameOffsetDown(StackSize);
 
-  // Early exit if we have no frame pointer.
-  if (!hasFP(MF)) {
-    return;
+  // Restore stack frame
+  if (HasFP) {
+    emitFrameAdjust(FP, MF, MBB, MBBI, StackSize);
+    BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), SP)
+      .addReg(FP)
+      .setMIFlag(MachineInstr::FrameSetup);
+  } else {
+    emitFrameAdjust(SP, MF, MBB, MBBI, StackSize);
   }
 
-  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
-  MachineFrameInfo &MFI = MF.getFrameInfo();
-  DebugLoc DL = MBBI->getDebugLoc();
-  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
-  const SuperHInstrInfo &TII = *STI.getInstrInfo();
+  // Restore return address from stack (if needed.)
+  if (MFI.hasCalls()) { 
+    BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
+      .addReg(SP)
+      .setMIFlag(MachineInstr::FrameDestroy);
+  }
 
-  uint32_t StackSize = MFI.getStackSize();
+  // Restore stack pointer
+  if (HasFP) {
+    BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLP), FP)
+      .addReg(SP)
+      .setMIFlag(MachineInstr::FrameDestroy);
+  }
 
-  if (STI.isPositionIndependent()) {
+  // TODO: Handle GOT
+}
 
-    // 1. Restore return address from stack.
-    if (MFI.hasCalls()) {
-      BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
-        .addReg(SP)
-        .setMIFlag(MachineInstr::FrameDestroy);
-    }
 
-    // 2. Delete stack frame, restoring stack pointer.
-    if (StackSize > 0) {
-      emitSPAdj(MF, MBB, MBBI, StackSize);
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
-        .addReg(SP)
-        .setMIFlag(MachineInstr::FrameDestroy);
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
-        .addReg(FP)
-        .setMIFlag(MachineInstr::FrameDestroy);
-    }
 
-  } else {
 
-    // 1. Restore return address from stack.
-    if (MFI.hasCalls()) {
-      BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
-        .addReg(SP)
-        .setMIFlag(MachineInstr::FrameDestroy);
-    }
-
-    // 2. Delete stack frame, restoring stack pointer.
-    //    add <stackadj>,r14
-    //    mov r14,r15
-    //    mov.l @r15+,r14
-    if (StackSize > 0) {
-      emitSPAdj(MF, MBB, MBBI, StackSize);
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
-        .addReg(SP)
-        .setMIFlag(MachineInstr::FrameDestroy);
-      BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), SP)
-        .addReg(FP)
-        .setMIFlag(MachineInstr::FrameDestroy);
-    }
-  }
-}
+//===--------------------------------------------------------------------------===//
+//                                Callee-Saves
+//===--------------------------------------------------------------------------===//
 
 void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
                         RegScavenger *RS) const {
@@ -301,24 +318,12 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
   return true;
 }
 
-StackOffset
-SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
-                                           Register &FrameReg) const {
-  const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
-  const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
-  bool HasFP = hasFP(MF);
 
-  // R14 base
-  int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
-  if (HasFP) {
-    FrameReg = RegInfo->getFrameRegister();
-    return StackOffset::getFixed(FrameOffset);
-  }
 
-  // R15 base
-  FrameReg = RegInfo->getStackRegister(); // %sp
-  return StackOffset::getFixed(FrameOffset + MF.getFrameInfo().getStackSize());
-}
+
+//===--------------------------------------------------------------------------===//
+//                               Call-Frame Meta
+//===--------------------------------------------------------------------------===//
 
 MachineBasicBlock::iterator
 SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF, 
@@ -342,6 +347,7 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
 
 bool SuperHFrameLowering::canSimplifyCallFramePseudos(
     const MachineFunction &MF) const {
+
   // Always simplify call frame pseudo instructions, even when
   // hasReservedCallFrame is false.
   return true;
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index 0f8bc43b4f4ce..eed0b6194cc49 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -44,6 +44,8 @@ class SuperHFrameLowering : public TargetFrameLowering {
 
   void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
                             RegScavenger *RS) const override;
+
+  void emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasicBlock::iterator MBBI, int32_t AdjValue) const;
   
 
   /// getFrameIndexReference - This method should return the base register
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 75f42e2b29467..86867e04273b2 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -107,6 +107,27 @@ static int64_t getLoadStoreBaseOffset(unsigned Opcode) {
   }
 }
 
+/// getLoadBaseOffset - Gets the neccesary bit shift amount for the
+/// load/store indexing
+static int64_t getLoadStoreOffsetShift(unsigned Opcode) {
+  switch(Opcode) {
+  case SH::MOVBL4:
+  case SH::MOVBS4:
+    return 0;
+
+  case SH::MOVWL4:
+  case SH::MOVWS4:
+    return 1;
+
+  case SH::MOVLS4:
+  case SH::MOVLL4:
+    return 2;
+
+  default:
+    return 0;
+  }
+}
+
 static void replaceFI(const MachineFunction &MF, MachineBasicBlock::iterator II,
                       MachineInstr &MI, const DebugLoc &dl,
                       unsigned FIOperandNum, int Offset, Register FramePtr) {
@@ -129,14 +150,11 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   const TargetInstrInfo &TII = *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
 
-  dbgs() << FrameIndex << " " << TII.getName(MI.getDesc().getOpcode()) << "\n";
-
   // Get the register offset to fetch.
   Register FrameReg;
   int64_t Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
-  Offset += MFI.getStackSize();
-
   int64_t ROff = getLoadStoreBaseOffset(MI.getOpcode());
+  int64_t Shift = getLoadStoreOffsetShift(MI.getOpcode());
 
   // Handle frame loads and stores.
   switch(MI.getOpcode()) {
@@ -145,9 +163,6 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   case SH::MOVBS4:
   case SH::MOVWS4: {
     Register SrcReg = MI.getOperand(0).getReg();
-
-    MI.dump();
-    dbgs() << "\n";
     
     // Expand sequence to
     // mov      <base reg>,r1
@@ -162,15 +177,12 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
     BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R0)
       .addReg(SrcReg);
 
-    Offset = ROff+Offset;
+    Offset = (ROff-Offset) >> Shift;
     FrameReg = SH::R1;
     break;
   }
   case SH::MOVLS4: {
 
-    MI.dump();
-    dbgs() << "\n";
-    
     // Expand sequence to
     // mov      <base reg>,r1
     // add      #-ROff,r1
@@ -180,7 +192,8 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
     BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
       .addReg(SH::R1)
       .addImm(-ROff);
-    Offset = ROff+Offset;
+
+    Offset = (ROff-Offset) >> Shift;
     FrameReg = SH::R1;
     break;
   }
@@ -206,7 +219,7 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
       .addReg(SH::R0)
       .addImm(-ROff);
 
-    Offset = ROff+Offset;
+    Offset = (ROff-Offset) >> Shift;
     FrameReg = SH::R1;
     break;
   }
@@ -221,7 +234,8 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
     BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
       .addReg(SH::R1)
       .addImm(-ROff);
-    Offset = ROff+Offset;
+
+    Offset = (ROff-Offset) >> Shift;
     FrameReg = SH::R1;
     break;
   }

>From 65f3961778c30bd46dbe2def9237980d45a16434 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 4 Sep 2026 16:22:10 +0200
Subject: [PATCH 38/67] Spill large constants to constpool

---
 llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp   | 20 +++-
 .../lib/Target/SuperH/SuperHFrameLowering.cpp | 11 ++-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  9 +-
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 94 +++++++++++++++----
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |  1 +
 llvm/lib/Target/SuperH/SuperHInstrFormats.td  |  2 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 30 +++++-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 35 ++++---
 .../SuperH/SuperHMachineFunctionInfo.cpp      | 33 +++++++
 .../Target/SuperH/SuperHMachineFunctionInfo.h |  1 +
 .../lib/Target/SuperH/SuperHTargetMachine.cpp | 10 +-
 11 files changed, 192 insertions(+), 54 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index 0baa06d54cfa7..7ae610276fbf4 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -47,6 +47,11 @@ class SuperHAsmPrinter : public AsmPrinter {
   /// pool entries so we can properly mark them as data regions.
   bool InConstantPool = false;
 
+  /// Set of globals in PromotedGlobals that we've emitted labels for.
+  /// We need to emit labels even for promoted globals so that DWARF
+  /// debug info can link properly.
+  SmallPtrSet<const GlobalVariable*,2> EmittedPromotedGlobalLabels;
+
 	SuperHTargetStreamer &getTargetStreamer() {
 		return static_cast<SuperHTargetStreamer &>(
 			*OutStreamer->getTargetStreamer());
@@ -183,8 +188,21 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
   if (Size < 4)
     Size = 4;
 
-  MCSymbol *MCSym;
+  // Handle promoted constants (eg. immediates that don't fit in 8 bits).
   SuperHConstantPoolValue *SCPV = static_cast<SuperHConstantPoolValue*>(MCPV);
+  if (SCPV->isPromotedGlobal()) {
+    auto *SCPC = cast<SuperHConstantPoolConstant>(SCPV);
+    for (const auto *GV : SCPC->promotedGlobals()) {
+      if (!EmittedPromotedGlobalLabels.count(GV)) {
+        MCSymbol *GVSym = getSymbol(GV);
+        OutStreamer->emitLabel(GVSym);
+        EmittedPromotedGlobalLabels.insert(GV);
+      }
+    }
+    return emitGlobalConstant(DL, SCPC->getPromotedGlobalInit());
+  } 
+
+  MCSymbol *MCSym;
   if (SCPV->isBlockAddress()) {
     const BlockAddress *BA =
       cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index fe6003e7244ae..834422c8419c1 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -161,7 +161,7 @@ SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
 //===--------------------------------------------------------------------------===//
 
 void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
-  LLVM_DEBUG(dbgs() << "Emitting prologue...\n");
+  LLVM_DEBUG(dbgs() << "Emitting prologue for " << MF.getName() << "...\n");
 
   MachineBasicBlock::iterator MBBI = MBB.begin();
   MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -181,6 +181,7 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
 
   // Store previous frame pointer.
   if (HasFP) {
+    adjustFrameOffsetDown(StackSize);
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), FP)
       .addReg(SP)
       .setMIFlag(MachineInstr::FrameSetup);
@@ -212,9 +213,9 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
 }
 
 void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
-  LLVM_DEBUG(dbgs() << "Emitting epilogue...\n");
+  LLVM_DEBUG(dbgs() << "Emitting epilogue for " << MF.getName() << "...\n");
 
-  MachineBasicBlock::iterator MBBI = MBB.begin();
+  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
   const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   const SuperHInstrInfo &TII = *STI.getInstrInfo();
@@ -223,6 +224,7 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
   Register FP = RII.getFrameRegister();
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
   bool HasFP = hasFP(MF);
+  
 
   // Get stack frame size.
   int64_t StackSize = MFI.getStackSize();
@@ -230,6 +232,7 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
 
   // Restore stack frame
   if (HasFP) {
+    adjustFrameOffsetDown(StackSize);
     emitFrameAdjust(FP, MF, MBB, MBBI, StackSize);
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), SP)
       .addReg(FP)
@@ -264,7 +267,6 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
 
 void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
                         RegScavenger *RS) const {
-  LLVM_DEBUG(dbgs() << "determineCalleeSaves\n");
   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 }
 
@@ -342,6 +344,7 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
   if (Amount == 0) {
     return MBB.erase(MI);
   }
+
   return MBB.erase(MI);
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index f89a607502340..e6822a465acca 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -198,6 +198,14 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
     }
   }
 
+  if (ConstantSDNode* Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
+      SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+      MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
+      ReplaceNode(N, Res);
+      return true;
+    }
+  }
   return false;
 }
 
@@ -305,7 +313,6 @@ bool SuperHDAGToDAGISel::trySelectBRCOND(SDNode *N) {
 
 
 
-
 //===----------------------------------------------------------------------===//
 //                             Branch Lowering
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 6ea55fc313a75..06e7ea01b9c7f 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -79,7 +79,6 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
     setTruncStoreAction(VT, MVT::i1, Promote);
   }
 
-
   // Division and remainders are multi-instruction sequences
   // on SuperH. Use a custom pass to lower those.
   for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
@@ -90,7 +89,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   }
 
   // Multiplies have multiple lowerings depending on size.
-  for (MVT VT : {MVT::i8, MVT::i16, MVT::i32}) {
+  for (MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64}) {
     setOperationAction(ISD::MUL, VT, Custom);
   }
 
@@ -98,7 +97,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
   setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
-
+  setOperationAction(ISD::Constant, MVT::i32, Custom);
 
   setOperationAction(ISD::BR_CC, MVT::i8, Custom);
   setOperationAction(ISD::BR_CC, MVT::i16, Custom);
@@ -115,6 +114,10 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::SETCC, MVT::i32, Custom);
   setOperationAction(ISD::SETCC, MVT::i64, Custom);
 
+  // for (MVT VT : MVT::integer_valuetypes()) {
+  //   setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Expand);
+  // }
+
   setBooleanContents(ZeroOrOneBooleanContent);
   setBooleanVectorContents(ZeroOrOneBooleanContent);
   setJumpIsExpensive(false);
@@ -188,6 +191,32 @@ SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
 
 
 
+//===----------------------------------------------------------------------===//
+//                            CONSTANT LOWERING
+//===----------------------------------------------------------------------===//
+
+SDValue SuperHTargetLowering::LowerConstant(SDValue Op, SelectionDAG &DAG) const {
+  DEBUG_FN_PRINT()
+
+  // Get the address of the target into a register
+  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
+    auto DL = SDLoc(C);
+
+    // Constant would fit in immediate
+    if (isInt<8>(C->getSExtValue())) {
+      return Op;
+    }
+
+    // Constant would NOT fit in immediate, lower to constpool.
+    SDValue Const = DAG.getSignedTargetConstant(C->getSExtValue(), DL, C->getValueType(0));
+    return DAG.getNode(SHISD::WRAPPER, DL, C->getValueType(0), Const);
+  }
+  return SDValue();
+}
+
+
+
+
 //===----------------------------------------------------------------------===//
 //                             ADDRESS LOWERING
 //===----------------------------------------------------------------------===//
@@ -255,16 +284,13 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
                        SmallVectorImpl<SDValue> &InVals) const {
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
-  MachineRegisterInfo &RegInfo = MF.getRegInfo();
   DataLayout DL = DAG.getDataLayout();
 
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
-
   SmallVector<CCValAssign, 16> ArgLocs;
   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext());
   CCInfo.AnalyzeFormalArguments(Ins, CC_SH);
 
-
   SDValue ArgValue;
   for (CCValAssign &VA : ArgLocs) {
 
@@ -432,6 +458,14 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
                  *DAG.getContext());
 
+  // Resolve the global value to jump to.
+  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+    Callee = LowerGlobalAddress(SDValue(G, 0), DAG);
+  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
+    Callee = LowerExternalSymbol(SDValue(S, 0), DAG);
+  }
+  CCInfo.AnalyzeCallOperands(Outs, CC_SH);
+
   // Get a count of how many bytes are to be pushed on the stack.
   unsigned NumBytes = CCInfo.getStackSize();
   Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL);
@@ -445,6 +479,26 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
     EVT RegVT = VA.getLocVT();
     SDValue Arg = OutVals[AI];
 
+    // Promote the value if needed. With Clang this should not happen.
+    switch (VA.getLocInfo()) {
+    default:
+      llvm_unreachable("Unknown loc info!");
+    case CCValAssign::Full:
+      break;
+    case CCValAssign::SExt:
+      Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, RegVT, Arg);
+      break;
+    case CCValAssign::ZExt:
+      Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, RegVT, Arg);
+      break;
+    case CCValAssign::AExt:
+      Arg = DAG.getNode(ISD::ANY_EXTEND, DL, RegVT, Arg);
+      break;
+    case CCValAssign::BCvt:
+      Arg = DAG.getNode(ISD::BITCAST, DL, RegVT, Arg);
+      break;
+    }
+
     // Stop when we encounter a stack argument, we need to process them
     // in reverse order in the loop below.
     if (VA.isMemLoc()) {
@@ -495,14 +549,6 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
     InGlue = Chain.getValue(1);
   }
 
-  // Resolve the global value to jump to.
-  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
-    Callee = LowerGlobalAddress(SDValue(G, 0), DAG);
-  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
-    Callee = LowerExternalSymbol(SDValue(S, 0), DAG);
-  }
-  InGlue = Chain.getValue(1);
-
   // Returns a chain & a flag for retval copy to use.
   SmallVector<SDValue, 8> Ops;
   Ops.push_back(Chain);
@@ -633,6 +679,7 @@ SDValue SuperHTargetLowering::LowerDIV(SDValue Op, SelectionDAG &DAG) const {
 //===----------------------------------------------------------------------===//
 //                          MULTIPLICATION LOWERING
 //===----------------------------------------------------------------------===//
+
 SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
   unsigned Opcode = Op->getOpcode();
   assert((Opcode == ISD::MUL) && "Invalid opcode for MUL lowering");
@@ -644,17 +691,24 @@ SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
   switch (VT.getSimpleVT().SimpleTy) {
   default:
     llvm_unreachable("Unexpected type for ");
+
   case MVT::i8: {
-    SDValue MulOp = DAG.getNode(SH::MULS, DL, MVT::i32, Op.getValue(0), Op.getValue(1));
-    return DAG.getNode(SH::LDSMACL, DL, MVT::i32, MulOp);
+    MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+    return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
   }
+
   case MVT::i16: {
-    SDValue MulOp = DAG.getNode(SH::MULS, DL, MVT::i32, Op.getValue(0), Op.getValue(1));
-    return DAG.getNode(SH::LDSMACL, DL, MVT::i32, MulOp);
+    MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+    return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
   }
 
   case MVT::i32: {
-    // 32-bit multiplication requires lowering to __mulsi3
+    MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+    return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
+  }
+
+  case MVT::i64: {
+    // 64-bit multiplication requires lowering to __mulsi3
     SDValue InChain = DAG.getEntryNode();
 
     TargetLowering::ArgListTy Args;
@@ -701,6 +755,8 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
     return LowerDIV(Op, DAG);
   case ISD::MUL:
     return LowerMUL(Op, DAG);
+  case ISD::Constant:
+    return LowerConstant(Op, DAG);
   case ISD::GlobalAddress:
     return LowerGlobalAddress(Op, DAG);
   case ISD::ExternalSymbol:
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index a7b29f3640372..0d73e0749958d 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -65,6 +65,7 @@ class SuperHTargetLowering : public TargetLowering  {
   SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerConstant(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerDIV(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index e8624d62397e5..5323f226da3a1 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -126,7 +126,7 @@ class InstRmRn<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
   
   // Opcode
   let Opcode = opcode;
-  let Inst{15-11} = Opcode{15-11};
+  let Inst{15-12} = Opcode{15-12};
   let Inst{3-0} = Opcode{3-0};
 
   // Operands
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 35447696b9a20..4b56c54fd9a44 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -118,7 +118,7 @@ const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
 
 
 //===----------------------------------------------------------------------===//
-//                              Stack Frames
+//                             Register Managment.
 //===----------------------------------------------------------------------===//
 
 void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
@@ -130,6 +130,20 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   if (SrcReg == DestReg)
     return;
 
+  // Load from MACL
+  if (SrcReg == SH::MACLO && SH::GPRRegClass.contains(DestReg)) {
+    BuildMI(MBB, MI, DL, get(SH::STSMACL), DestReg)
+      .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
+  // Store to MACL
+  if (SH::GPRRegClass.contains(SrcReg) && DestReg == SH::MACLO) {
+    BuildMI(MBB, MI, DL, get(SH::LDSMACL), DestReg)
+      .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
   // If the targets are GPR registers, use MOV Rm, Rn.
   if (SH::GPRRegClass.contains(DestReg, SrcReg)) {
     BuildMI(MBB, MI, DL, get(SH::MOV), DestReg)
@@ -141,6 +155,14 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   llvm_unreachable("Impossible reg-to-reg copy");
 }
 
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                              Stack Frames
+//===----------------------------------------------------------------------===//
+
 void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 
                                           Register SrcReg, bool isKill, int FrameIndex, 
                                           const TargetRegisterClass *RC, Register VReg, 
@@ -354,10 +376,10 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
           MBB.isLayoutSuccessor(TargetBB)) {
 
         BranchCode = getOppositeCondCode(BranchCode);
-        unsigned JNCC = getBrCond(BranchCode).getOpcode();
-        MachineBasicBlock::iterator OldInst = I;
+        auto JNCC = getBrCond(BranchCode);
 
-        BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
+        MachineBasicBlock::iterator OldInst = I;
+        BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), JNCC)
             .addMBB(UnCondBrIter->getOperand(0).getMBB());
         BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SH::BRA))
             .addMBB(TargetBB);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 7e1c22e132a61..766d6199fb376 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -128,13 +128,18 @@ class SHRegIndirectClass<string op> : SHOpClass<"IReg" # op> {
 
 // Immediate
 class SHImmOp<int width, ValueType vt>
-      : Operand<vt> {
+      : Operand<vt>, ImmLeaf<vt, [{ return isInt<}] # width # [{>(Imm); }]> {
     let ParserMatchClass = SHImmClass<width>;
     let OperandType = "OPERAND_IMMEDIATE";
     let PrintMethod = "printImm";
-    let MCOperandPredicate = [{int64_t Imm; return MCOp.evaluateAsConstantImm(Imm) ? isInt<}] # width # [{>(Imm) : false;}];
+    let MCOperandPredicate = [{
+      int64_t Imm;
+      if (MCOp.evaluateAsConstantImm(Imm))
+        return isInt<}] # width # [{>(Imm)
+      return false;
+    }];
 }
-def imm8 : SHImmOp<8, i32>, ImmLeaf<i32, [{ return isInt<8>(Imm); }]>;
+def imm8 : SHImmOp<8, i32>;
 
 // Displacement
 class SHDispOp<int width, ValueType vt>
@@ -564,7 +569,7 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
   def ADDI          : InstRnI8<0b0111000000000000, 
                               (outs GPR:$Rn), (ins GPR:$src, imm8:$imm),
                               "add $imm,$Rn",
-                              [(set i32:$Rn, (add i32:$src, imm8:$imm))]>;
+                              [(set i32:$Rn, (add i32:$src, imm:$imm))]>;
 
   // addc Rm, Rn
   let Defs = [SR], Uses = [SR], isCommutable = 1 in
@@ -641,54 +646,54 @@ let hasSideEffects = 0 in {
 // Multiplication
 //===--------------------------------------------------------------------------===//
 
-let hasSideEffects = 0, isCommutable = 1, Constraints = "$src = $Rn" in {
+let hasSideEffects = 0, isCommutable = 1 in {
 
   // mac.w @Rm+, @Rn+
   let Defs = [MACLO] in
   def MACW      : InstRmRn<0b0100000000001111, 
-                              (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
+                              (outs), (ins IGPRInc:$Rm, IGPRInc:$Rn),
                               "mac.w $Rm,$Rn",
                               []>;
 
   // mac.l @Rm+, @Rn+
   let Defs = [MACLO, MACHI] in
   def MACL          : InstRmRn<0b0000000000001111, 
-                              (outs GPR:$Rn), (ins IGPRInc:$Rm, IGPRInc:$src),
+                              (outs), (ins IGPRInc:$Rm, IGPRInc:$Rn),
                               "mac.l $Rm,$Rn",
                               []>;
 
   // mul.l Rm, Rn
   let Defs = [MACLO] in
   def MULL          : InstRmRn<0b0000000000000111, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
                               "mul.l $Rm,$Rn",
                               []>;
 
   // muls.w Rm, Rn
   let Defs = [MACLO] in
   def MULS          : InstRmRn<0b0010000000001111, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
                               "muls.w $Rm,$Rn",
                               []>;
 
   // mulu.w Rm, Rn
   let Defs = [MACLO] in
   def MULU          : InstRmRn<0b0010000000001110, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
                               "mulu.w $Rm,$Rn",
                               []>;
 
   // dmuls.l Rm, Rn
   let Defs = [MACLO, MACHI] in
   def DMULS         : InstRmRn<0b0011000000001101, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
                               "dmuls.l $Rm,$Rn",
                               []>;
 
   // dmulu.l Rm, Rn
   let Defs = [MACLO, MACHI] in
   def DMULU         : InstRmRn<0b0011000000000101, 
-                              (outs GPR:$Rn), (ins GPR:$Rm, GPR:$src),
+                              (outs), (ins GPR:$Rm, GPR:$Rn),
                               "dmulu.l $Rm,$Rn",
                               []>;
 }
@@ -1371,9 +1376,9 @@ include "SuperHInstrDSP.td"
 // def : Pat<(i32 (sextloadi8  i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
 // def : Pat<(i32 (sextloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
 
-// def : Pat<(sext_inreg i32:$src, i1),  (EXTSBRmRn i32:$src)>;
-// def : Pat<(sext_inreg i32:$src, i8),  (EXTSBRmRn i32:$src)>;
-// def : Pat<(sext_inreg i32:$src, i16), (EXTSWRmRn i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i1),  (EXTSB i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i8),  (EXTSB i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i16), (EXTSW i32:$src)>;
 
 //===--------------------------------------------------------------------------===//
 // Truncating Store
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
index 139e969eb1548..f25c7be39daf3 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -93,6 +93,39 @@ SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
   );
 }
 
+SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
+        ConstantSDNode *N, 
+        SelectionDAG &DAG, 
+        SHCP::SHCPModifier Modifier) {
+
+  // Early exit for null node.
+  if (!N)
+    return nullptr;
+
+  // Run though the constant pool that is tied to the DAG and search for 
+  // the constant there.
+  MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+  for (auto &MC : MCP->getConstants()) {
+    if (MC.isMachineConstantPoolEntry()) {
+      if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+        if (CPV->getPromotedGlobalInit() == N->getConstantIntValue())
+          return CPV;
+      }
+    }
+  }
+
+  // If not found, create a new one and add it.
+  MachineFunction &MF = DAG.getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+  unsigned LabelIndex = SFI->createConstIndex();
+  return SuperHConstantPoolConstant::Create(
+    N->getConstantIntValue(), 
+    LabelIndex,
+    SHCP::SHCPKind::CPPromotedGlobal,
+    Modifier
+  );
+}
+
 SuperHConstantPoolSymbol *SuperHMachineFunctionInfo::tryGetConstant(
         ExternalSymbolSDNode *N, 
         SelectionDAG &DAG, 
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
index c330e0b4ec931..db3fade2466ae 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -59,6 +59,7 @@ class SuperHMachineFunctionInfo : public MachineFunctionInfo {
   //     a PC-relative load.
   SuperHConstantPoolConstant *tryGetConstant(GlobalAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
   SuperHConstantPoolConstant *tryGetConstant(BlockAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant *tryGetConstant(ConstantSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
   SuperHConstantPoolSymbol *tryGetConstant(ExternalSymbolSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
 
 private:
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index c39f3d643d94f..3118603fe51d0 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -48,8 +48,6 @@ class SuperHPassConfig : public TargetPassConfig {
     : TargetPassConfig(TM, PM) {}
 
   bool addInstSelector() override;
-  void addPreSched2() override;
-  void addPreEmitPass() override;
   void addPreEmitPass2() override;
   SuperHTargetMachine &getSuperHTargetMachine() const {
     return getTM<SuperHTargetMachine>();
@@ -61,14 +59,8 @@ bool SuperHPassConfig::addInstSelector() {
   return false;
 }
 
-void SuperHPassConfig::addPreSched2() {
-}
-
-void SuperHPassConfig::addPreEmitPass() {
-  addPass(createSuperHFillDelaySlotsPass());
-}
-
 void SuperHPassConfig::addPreEmitPass2() {
+  addPass(createSuperHFillDelaySlotsPass());
 
   // Inserts Constant Islands. Block sizes cannot be increased after this point,
   // as this may push the branch ranges and load offsets of accessing constant

>From e6ce37fdf7766adc5798a383dccc9ba3b10eb38c Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 6 Sep 2026 14:41:09 +0200
Subject: [PATCH 39/67] More refactoring of stack frame

---
 llvm/lib/Target/SuperH/CMakeLists.txt         |   1 +
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |  34 +-
 .../SuperH/MCTargetDesc/SuperHInstPrinter.h   |   9 +-
 .../MCTargetDesc/SuperHMCCodeEmitter.cpp      |  71 +++-
 llvm/lib/Target/SuperH/README.txt             |  18 +
 llvm/lib/Target/SuperH/SuperH.h               |   2 +
 llvm/lib/Target/SuperH/SuperHCallingConv.td   |   4 -
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 362 ++++++++++++++++++
 .../Target/SuperH/SuperHFillDelaySlots.cpp    |   9 +-
 .../lib/Target/SuperH/SuperHFrameLowering.cpp |  33 +-
 llvm/lib/Target/SuperH/SuperHFrameLowering.h  |   1 -
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp |  11 +-
 llvm/lib/Target/SuperH/SuperHInstrFormats.td  |  10 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 166 ++++----
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |   6 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 185 +++++----
 llvm/lib/Target/SuperH/SuperHMCInstLower.cpp  |   1 +
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 155 +-------
 llvm/lib/Target/SuperH/SuperHRegisterInfo.h   |   1 +
 .../lib/Target/SuperH/SuperHTargetMachine.cpp |   6 +
 20 files changed, 717 insertions(+), 368 deletions(-)
 create mode 100644 llvm/lib/Target/SuperH/README.txt
 create mode 100644 llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp

diff --git a/llvm/lib/Target/SuperH/CMakeLists.txt b/llvm/lib/Target/SuperH/CMakeLists.txt
index a09955850e10a..365ad91100316 100644
--- a/llvm/lib/Target/SuperH/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/CMakeLists.txt
@@ -32,6 +32,7 @@ add_llvm_target(SuperHCodeGen
   SuperHSubtarget.cpp
   SuperHFillDelaySlots.cpp
   SuperHConstantIslandPass.cpp
+  SuperHExpandPseudoInsts.cpp
 
   LINK_COMPONENTS
   Analysis
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 1a6148b27ca70..1ecc1b8fbc0d9 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -15,6 +15,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Debug.h"
 
@@ -45,17 +46,6 @@ void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
   OS << getRegName(Reg);
 }
 
-void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
-  const MCOperand &Op0 = MI->getOperand(OpNo);
-  const MCOperand &Op1 = MI->getOperand(OpNo+1);
-  OS << "@(" << Op1.getImm() << "," << getRegName(Op0.getReg()) << ")";
-}
-
-void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
-  const MCOperand &Op = MI->getOperand(OpNo);
-  OS << Op.getImm();
-}
-
 void SuperHInstPrinter::printImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
   OS << "#" << Op.getImm();
@@ -76,7 +66,14 @@ void SuperHInstPrinter::printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostrea
   OS << "@-" << getRegName(Op.getReg());
 }
 
-void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address, 
+template<int Scale>
+void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+  const MCOperand &Op = MI->getOperand(OpNo);
+  OS << Op.getImm();
+}
+
+template<int Scale>
+void SuperHInstPrinter::printPCRel(const MCInst *MI, uint64_t Address, 
                                       unsigned OpNo, raw_ostream &O) {
   const MCOperand &Op = MI->getOperand(OpNo);
 
@@ -94,6 +91,19 @@ void SuperHInstPrinter::printPCRelImm(const MCInst *MI, uint64_t Address,
   }
 }
 
+template<int Scale>
+void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+
+  // Skip "Uses" operands, as some Memri operations are destinations.
+  if (MI->getOperand(OpNo+1).isReg())
+    OpNo++;
+
+  const MCOperand &Op0 = MI->getOperand(OpNo);
+  const MCOperand &Op1 = MI->getOperand(OpNo+1);
+
+  OS << "@(" << Op1.getImm() << "," << getRegName(Op0.getReg()) << ")";
+}
+
 void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
   printOperand(MI, OpNo, O);
 }
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index 328c42c366b24..230b3e8cc83e6 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -51,9 +51,14 @@ class SuperHInstPrinter : public MCInstPrinter {
   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
 
-  void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
-  void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  template<int Scale>
+  void printPCRel(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
+  
+  template<int Scale>
   void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+
+  template<int Scale>
+  void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 1c8a76dcc7467..848cff47c4ace 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -14,6 +14,7 @@
 #include "SuperHFixupKinds.h"
 #include "SuperHMCTargetDesc.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/MC/MCAsmInfo.h"
@@ -71,12 +72,21 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
 
   unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
                           SmallVectorImpl<MCFixup> &Fixups,
-                          const MCSubtargetInfo &STI) const;
+                          const MCSubtargetInfo &STI,
+                          int64_t Shift) const;
 
   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
+  
+  // Displacement
+  template<int Scale>
+  unsigned getDispOpValue(const MCInst &MI, unsigned OpNo,
+                          SmallVectorImpl<MCFixup> &Fixups,
+                          const MCSubtargetInfo &STI) const;
 
+  // PC-relative displacement.
+  template<int Scale>
   unsigned getPCRelOpValue(const MCInst &MI, unsigned OpNo,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
@@ -201,28 +211,73 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
   ++MCNumEmitted;
 }
 
+
+
+
+//===----------------------------------------------------------------------===//
+//                              Branch Target
+//===----------------------------------------------------------------------===//
+
 unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                                                      SmallVectorImpl<MCFixup> &Fixups,
                                                      const MCSubtargetInfo &STI) const {
   return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
 }
 
-unsigned SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
+
+
+
+//===----------------------------------------------------------------------===//
+//                                Displacement
+//===----------------------------------------------------------------------===//
+
+template<int Scale>
+unsigned SuperHMCCodeEmitter::getDispOpValue(const MCInst &MI, unsigned OpNo,
                                               SmallVectorImpl<MCFixup> &Fixups,
                                               const MCSubtargetInfo &STI) const {
+  // Skip base register if found.
+  if (MI.getOperand(OpNo).isReg())
+    OpNo++;
+
+  auto MO = MI.getOperand(OpNo);
+  if (MO.isImm())
+    return (MO.getImm() / Scale);
+
+  assert(MO.isExpr() && "Expected Expression");
   return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
 }
 
-unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
-                                             SmallVectorImpl<MCFixup> &Fixups,
-                                             const MCSubtargetInfo &STI) const {
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                          PC-Relative Displacement
+//===----------------------------------------------------------------------===//
+
+template<int Scale>
+unsigned SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
+                                              SmallVectorImpl<MCFixup> &Fixups,
+                                              const MCSubtargetInfo &STI) const {
+  auto MO = MI.getOperand(OpNo);
+  if (MO.isImm())
+    return MO.getImm() / Scale;
+
+  assert(MO.isExpr() && "Expected Expression");
+  return getExprOpValue(MI, MO.getExpr(), Fixups, STI, Scale);
+}
+
+unsigned 
+SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
+                                    SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI, 
+                                    int64_t Shift) const {
   if (!Expr)
     return 0;
 
   switch(Expr->getKind()) {
   case MCExpr::ExprKind::Binary: {
-    unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI);
-    Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI);
+    unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI, Shift);
+    Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI, Shift);
     return Res;
   }
   case MCExpr::ExprKind::Target: {
@@ -259,7 +314,7 @@ unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI,
     return MO.getImm();
 
   assert(MO.isExpr() && "Expected Expression");
-  return getExprOpValue(MI, MO.getExpr(), Fixups, STI);
+  return getExprOpValue(MI, MO.getExpr(), Fixups, STI, 0);
 }
 
 MCCodeEmitter *llvm::createSuperHMCCodeEmitter(const MCInstrInfo &MCII,
diff --git a/llvm/lib/Target/SuperH/README.txt b/llvm/lib/Target/SuperH/README.txt
new file mode 100644
index 0000000000000..6c34f247541fc
--- /dev/null
+++ b/llvm/lib/Target/SuperH/README.txt
@@ -0,0 +1,18 @@
+//===---------------------------------------------------------------------===//
+// Ideas for the backend.
+//===---------------------------------------------------------------------===//
+
+  * Improve SuperHFillDelaySlots pass to fill delay slots from branch
+    destinations.
+
+  * Add more variations to MOV*SFR and MOV*SFR for large stack sizes.
+  * Improve compactness of constant islands.
+
+//===---------------------------------------------------------------------===//
+// Known Issues
+//===---------------------------------------------------------------------===//
+
+  * Only SH2 level codegen is implemented.
+  * O1 compilation fails due to misgenerated fallthrough MBBs
+  * 64-bit integers are not handled.
+  * Varargs are not implemented.
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index 911234e3efefc..450191c721631 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -28,12 +28,14 @@ class SuperHTargetMachine;
 FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel);
 FunctionPass *createSuperHFillDelaySlotsPass();
 FunctionPass *createSuperHConstantIslandPass();
+FunctionPass *createSuperHExpandPseudoPass();
 
 void initializeSuperHDAGToDAGISelLegacyPass(PassRegistry &);
 void initializeSuperHAsmPrinterPass(PassRegistry &);
 void initializeSuperHAsmPrinterPass(PassRegistry &);
 void initializeSuperHFillDelaySlotsPass(PassRegistry &);
 void initializeSuperHConstantIslandsPass(PassRegistry &);
+void initializeSuperHExpandPseudoPass(PassRegistry &);
 } // namespace llvm
 
 
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index 71d899d3c7e8b..20dc3f3ad42d9 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -26,10 +26,6 @@ def RetCC_SH : CallingConv<[
   CCIfType<[i1, i8, i16],  CCPromoteToType<i32>>,
   CCIfType<[i32],  CCAssignToReg<[R0, R1, R2, R3]>>,
   CCIfType<[i64],  CCAssignToReg<[R0, R1]>>,
-
-  // Anything that doesn't fit in registers should be spilled.
-  CCIfType<[i32], CCAssignToStack<4, 4>>,
-  CCIfType<[i64], CCAssignToStack<8, 4>>,
 ]>;
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
new file mode 100644
index 0000000000000..5daf40e32f1d7
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -0,0 +1,362 @@
+//===-- SuperHExpandPseudoInsts.cpp - Expand pseudo instructions ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that expands pseudo instructions into target
+// instructions. This pass should be run after register allocation but before
+// the post-regalloc scheduling pass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuperH.h"
+#include "SuperHInstrInfo.h"
+#include "SuperHTargetMachine.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
+
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sh-expand-pseudo"
+#define SH_EXPAND_PSEUDO_NAME "SH pseudo instruction expansion pass"
+
+namespace {
+class SuperHExpandPseudo : public MachineFunctionPass {
+public:
+  static char ID;
+
+  SuperHExpandPseudo() : MachineFunctionPass(ID) {}
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  StringRef getPassName() const override { return SH_EXPAND_PSEUDO_NAME; }
+
+private:
+  typedef MachineBasicBlock Block;
+  typedef Block::iterator BlockIt;
+
+  const SuperHRegisterInfo *TRI;
+  const TargetInstrInfo *TII;
+
+  bool expandMBB(Block &MBB);
+  bool expandMI(Block &MBB, BlockIt MBBI);
+  template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
+};
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                                Helpers
+//===----------------------------------------------------------------------===//
+
+// getOffsetForStackOffset - Calculates how much to offset the stack pointer for
+// the indirect load/store to be in range.
+static int64_t getOffsetForStackOffset(const MachineFrameInfo &MFI, int64_t StackOffset, 
+                                       uint8_t Bits, uint8_t Scale = 1) {
+  
+  // The base value range for the instruction.
+  int64_t BM = ((1<<Bits)-1)*Scale;
+  int64_t StackSize = MFI.getStackSize();
+  int64_t Slot = StackSize/BM;
+  return alignTo((BM*Slot)+(StackSize%BM), Scale);
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//                              Frame Stores
+//===----------------------------------------------------------------------===//
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVBSFR>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  auto SrcReg = MI.getOperand(0).getReg();
+  auto FrameReg = MI.getOperand(1).getReg();
+  auto Offset = MI.getOperand(2).getImm();
+  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 1);
+
+  LLVM_DEBUG(dbgs() << "Expanding MOVBSFR to MOVBS4...\n");
+
+  // Expand sequence to
+  // mov      <base reg>,r1
+  // add      #-ROff,r1
+  // mov      <src reg>, r0
+  // mov.b    r0,@(ROff+Offset,r1)
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+    .addReg(FrameReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+    .addReg(SH::R1)
+    .addImm(-SpOffset);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
+    .addReg(SrcReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS4))
+    .addReg(SH::R1)
+    .addImm(SpOffset-Offset);
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVWSFR>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  auto SrcReg = MI.getOperand(0).getReg();
+  auto FrameReg = MI.getOperand(1).getReg();
+  auto Offset = MI.getOperand(2).getImm();
+  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 2);
+
+  LLVM_DEBUG(dbgs() << "Expanding MOVWSFR to MOVWS4...\n");
+
+  // Expand sequence to
+  // mov      <base reg>,r1
+  // add      #-ROff,r1
+  // mov      <src reg>, r0
+  // mov.w    r0,@(ROff+Offset,r1)
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+    .addReg(FrameReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+    .addReg(SH::R1)
+    .addImm(-SpOffset);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
+    .addReg(SrcReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS4))
+    .addReg(SH::R1)
+    .addImm(SpOffset-Offset);
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVLSFR>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  auto SrcReg = MI.getOperand(0).getReg();
+  auto FrameReg = MI.getOperand(1).getReg();
+  auto Offset = MI.getOperand(2).getImm();
+  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 4);
+
+  LLVM_DEBUG(dbgs() << "Expanding MOVLSFR to MOVLS4...\n");
+    
+  // Expand sequence to
+  // mov      <base reg>,r1
+  // add      #-ROff,r1
+  // mov.l    <src reg>,@(ROff+Offset,r1)
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+    .addReg(FrameReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+    .addReg(SH::R1)
+    .addImm(-SpOffset);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
+    .addReg(SrcReg)
+    .addReg(SH::R1)
+    .addImm(SpOffset-Offset);
+  MI.eraseFromParent();
+  return true;
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                               Frame Loads
+//===----------------------------------------------------------------------===//
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVBLFR>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  LLVM_DEBUG(dbgs() << "Expanding MOVBLFR to MOVBL4...\n");
+
+  auto DstReg = MI.getOperand(0).getReg();
+  auto FrameReg = MI.getOperand(1).getReg();
+  auto Offset = MI.getOperand(2).getImm();
+  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 1);
+
+  // HACK:  Need to find a better way of handling this, it's likely to break.
+  MBBI = std::next(MBBI);
+  MBBI = std::next(MBBI);
+    
+  // Expand sequence to
+  // mov      <base reg>,r1
+  // add      #-ROff,r1
+  // mov.b    @(ROff+Offset,r1),r0
+  // mov      r0, <dst reg>
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+    .addReg(FrameReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+    .addReg(SH::R1)
+    .addImm(-SpOffset);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL4))
+    .addReg(SH::R1)
+    .addImm(SpOffset-Offset);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), DstReg)
+    .addReg(SH::R0);
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVWLFR>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  LLVM_DEBUG(dbgs() << "Expanding MOVWLFR to MOVWL4...\n");
+
+  auto DstReg = MI.getOperand(0).getReg();
+  auto FrameReg = MI.getOperand(1).getReg();
+  auto Offset = MI.getOperand(2).getImm();
+  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 2);
+
+  // HACK:  Need to find a better way of handling this, it's likely to break.
+  MBBI = std::next(MBBI);
+  MBBI = std::next(MBBI);
+    
+  // Expand sequence to
+  // mov      <base reg>,r1
+  // add      #-ROff,r1
+  // mov.w    @(ROff+Offset,r1),r0
+  // mov      r0, <dst reg>
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+    .addReg(FrameReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+    .addReg(SH::R1)
+    .addImm(-SpOffset);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4))
+    .addReg(SH::R1)
+    .addImm(SpOffset-Offset);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), DstReg)
+    .addReg(SH::R0);
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVLLFR>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  auto DstReg = MI.getOperand(0).getReg();
+  auto FrameReg = MI.getOperand(1).getReg();
+  auto Offset = MI.getOperand(2).getImm();
+  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 4);
+
+  LLVM_DEBUG(dbgs() << "Expanding MOVLLFR to MOVLL4...\n");
+    
+  // Expand sequence to
+  // mov      <base reg>,r1
+  // add      #-ROff,r1
+  // mov.l    @(ROff+Offset,r1),<dest reg>
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+    .addReg(FrameReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+    .addReg(SH::R1)
+    .addImm(-SpOffset);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4), DstReg)
+    .addReg(SH::R1)
+    .addImm(SpOffset-Offset);
+  MI.eraseFromParent();
+  return true;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+//                            General Interface
+//===----------------------------------------------------------------------===//
+
+bool SuperHExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
+  bool Modified = false;
+
+  BlockIt MBBI = MBB.begin(), E = MBB.end();
+  while (MBBI != E) {
+    BlockIt NMBBI = std::next(MBBI);
+    Modified |= expandMI(MBB, MBBI);
+    MBBI = NMBBI;
+  }
+
+  return Modified;
+}
+
+bool SuperHExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
+  bool Modified = false;
+
+  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
+  TRI = STI.getRegisterInfo();
+  TII = STI.getInstrInfo();
+
+  for (Block &MBB : MF) {
+    bool ContinueExpanding = true;
+    unsigned ExpandCount = 0;
+
+    // Continue expanding the block until all pseudos are expanded.
+    do {
+      assert(ExpandCount < 10 && "pseudo expand limit reached");
+      (void)ExpandCount;
+
+      bool BlockModified = expandMBB(MBB);
+      Modified |= BlockModified;
+      ExpandCount++;
+
+      ContinueExpanding = BlockModified;
+    } while (ContinueExpanding);
+  }
+
+  return Modified;
+}
+
+bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
+  MachineInstr &MI = *MBBI;
+  int Opcode = MBBI->getOpcode();
+
+#define EXPAND(Op)                                                             \
+  case Op:                                                                     \
+    return expand<Op>(MBB, MI)
+
+  switch(Opcode) {
+    EXPAND(SH::MOVBSFR);
+    EXPAND(SH::MOVWSFR);
+    EXPAND(SH::MOVLSFR);
+    EXPAND(SH::MOVBLFR);
+    EXPAND(SH::MOVWLFR);
+    EXPAND(SH::MOVLLFR);
+  }
+#undef EXPAND
+  return false;
+}
+
+char SuperHExpandPseudo::ID = 0;
+
+} // namespace
+
+
+INITIALIZE_PASS(SuperHExpandPseudo, "sh-expand-pseudo", SH_EXPAND_PSEUDO_NAME,
+                false, false)
+
+FunctionPass *llvm::createSuperHExpandPseudoPass() {
+  return new SuperHExpandPseudo();
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index d3f950bfb7477..5fd82e22c68bc 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -68,11 +68,18 @@ class SuperHFillDelaySlots : public MachineFunctionPass {
 // for filling delay slots.
 MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI) {
   MachineInstr &MI = *MBBI;
+  auto *Prev = MBBI->getPrevNode();
 
+  // We might have a useful instruction above the instruction that
+  // loads our destination address.
+  if (MI.isCall() && Prev) {
+    if (!Prev->getPrevNode()->definesRegister(MI.getOperand(0).getReg(), TRI))
+      Prev = Prev->getPrevNode();
+  }
 
   // TODO:  Make this a while loop that keeps a list of "used" registers
   //        by instructions.
-  if (auto *Prev = MBBI->getPrevNode()) {
+  if (Prev) {
     unsigned Opcode = Prev->getOpcode();
 
     // If we encounter a branch instruction, then it's no longer safe to
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 834422c8419c1..db3b35cb06a8d 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -17,10 +17,15 @@
 #include "SuperHInstrInfo.h"
 #include "SuperHRegisterInfo.h"
 #include "SuperHSubtarget.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCRegister.h"
 #include "llvm/Support/Debug.h"
@@ -122,35 +127,36 @@ void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, Ma
     .setMIFlag(MFlag);
 }
 
+
+
+
+//===--------------------------------------------------------------------------===//
+//                              Call-Frame Objects
+//===--------------------------------------------------------------------------===//
+
 StackOffset
 SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
                                            Register &FrameReg) const {
   const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
   const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
   bool HasFP = hasFP(MF);
 
   // NOTE:  All the frame indices are relative to the stack/frame pointer
   //        post-offset. as such an extra adjustment is needed here.
-  int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI);
-  FrameOffset += MFI.getStackSize() - TFI->getOffsetOfLocalArea();
-  
-  // Adjust down to remove SP.
-  adjustFrameOffsetDown(FrameOffset);
+  int64_t FrameOffset = MFI.getObjectOffset(FI);
 
   // R14 base
   if (HasFP) {
 
     // Adjust down to remove FP.
-    adjustFrameOffsetDown(FrameOffset);
     FrameReg = RegInfo->getFrameRegister();
-    return StackOffset::getFixed(FrameOffset);
+    return StackOffset::getFixed(-FrameOffset);
   }
 
   // R15 base
   FrameReg = RegInfo->getStackRegister(); // r15
-  return StackOffset::getFixed(FrameOffset);
+  return StackOffset::getFixed(-FrameOffset);
 }
 
 
@@ -177,11 +183,9 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
 
   // Get stack frame size.
   int64_t StackSize = MFI.getStackSize();
-  adjustFrameOffsetDown(StackSize);
 
   // Store previous frame pointer.
   if (HasFP) {
-    adjustFrameOffsetDown(StackSize);
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), FP)
       .addReg(SP)
       .setMIFlag(MachineInstr::FrameSetup);
@@ -224,15 +228,13 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
   Register FP = RII.getFrameRegister();
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
   bool HasFP = hasFP(MF);
-  
+
 
   // Get stack frame size.
   int64_t StackSize = MFI.getStackSize();
-  adjustFrameOffsetDown(StackSize);
 
   // Restore stack frame
   if (HasFP) {
-    adjustFrameOffsetDown(StackSize);
     emitFrameAdjust(FP, MF, MBB, MBBI, StackSize);
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), SP)
       .addReg(FP)
@@ -285,7 +287,7 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
   const TargetInstrInfo &TII = *STI.getInstrInfo();
   Register SP = RII.getStackRegister();
 
-  for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
+  for (const CalleeSavedInfo &I : reverse(CSI)) {
     MCRegister Reg = I.getReg();
     BuildMI(MBB, MI, DL, TII.get(SH::MOVLM), SP)
       .addReg(Reg)
@@ -344,7 +346,6 @@ SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF,
   if (Amount == 0) {
     return MBB.erase(MI);
   }
-
   return MBB.erase(MI);
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index eed0b6194cc49..10a8f8ac65b85 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -46,7 +46,6 @@ class SuperHFrameLowering : public TargetFrameLowering {
                             RegScavenger *RS) const override;
 
   void emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasicBlock::iterator MBBI, int32_t AdjValue) const;
-  
 
   /// getFrameIndexReference - This method should return the base register
   /// and offset used to reference a frame index location. The offset is
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 06e7ea01b9c7f..e1ed74ae00814 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -28,6 +28,7 @@
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/TargetLowering.h"
@@ -67,7 +68,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
 
   setSchedulingPreference(Sched::RegPressure);
   setSupportsUnalignedAtomics(false);
-  setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
+  // setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
 
   // Loads and stores are legal
   for (MVT VT : MVT::integer_valuetypes()) {
@@ -122,6 +123,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setBooleanVectorContents(ZeroOrOneBooleanContent);
   setJumpIsExpensive(false);
   setMinFunctionAlignment(Align(4));
+  setMinStackArgumentAlignment(Align(4));
 }
 
 //===----------------------------------------------------------------------===//
@@ -576,10 +578,7 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
 
   // Create the CALLSEQ_END node.
   Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
-
-  if (!Ins.empty()) {
-    InGlue = Chain.getValue(1);
-  }
+  InGlue = Chain.getValue(1);
 
   return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG, InVals);
 }
@@ -601,6 +600,7 @@ SDValue SuperHTargetLowering::LowerCallResult(
   for (CCValAssign const &RVLoc : RVLocs) {
     Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(), InGlue)
                 .getValue(1);
+
     InGlue = Chain.getValue(2);
     InVals.push_back(Chain.getValue(0));
   }
@@ -782,7 +782,6 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
 
 
 
-
 //===----------------------------------------------------------------------===//
 //                          SelectCC/SetCC Lowering
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index 5323f226da3a1..11ad66fe6a24a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -88,12 +88,12 @@ class SHSelectPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
 
 class SHLoadPseudo<dag outs, dag ins, string asmstr, list<dag> pattern> 
       : SHPseudo<outs, ins, asmstr, pattern> {
-  let usesCustomInserter = 1;
+  let mayLoad = 1;
 }
 
 class SHStorePseudo<dag outs, dag ins, string asmstr, list<dag> pattern> 
       : SHPseudo<outs, ins, asmstr, pattern> {
-  let usesCustomInserter = 1;
+  let mayStore = 1;
 }
 
 
@@ -224,7 +224,7 @@ class InstRmRnD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> pa
   bits<4> disp;
   let Inst{11-8} = Rn;
   let Inst{7-4} = Rm;
-  let Inst{0-3} = disp;
+  let Inst{3-0} = disp;
 }
 
 //===----------------------------------------------------------------------===//
@@ -242,7 +242,7 @@ class InstRnD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
   bits<4> Rn;
   bits<4> disp;
   let Inst{7-4} = Rn;
-  let Inst{0-3} = disp;
+  let Inst{3-0} = disp;
 }
 
 //===----------------------------------------------------------------------===//
@@ -260,7 +260,7 @@ class InstRmD4<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patt
   bits<4> Rm;
   bits<4> disp;
   let Inst{7-4} = Rm;
-  let Inst{0-3} = disp;
+  let Inst{3-0} = disp;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 4b56c54fd9a44..94bc9ceade1cc 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -18,6 +18,7 @@
 #include "MCTargetDesc/SuperHInstPrinter.h"
 #include "SuperH.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstr.h"
@@ -113,6 +114,28 @@ const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
   }
 }
 
+unsigned SuperHInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
+  unsigned Opcode = MI.getOpcode();
+
+  switch (Opcode) {
+  // A regular instruction
+  default: {
+    const MCInstrDesc &Desc = get(Opcode);
+    return Desc.getSize();
+  }
+  case TargetOpcode::EH_LABEL:
+  case TargetOpcode::IMPLICIT_DEF:
+  case TargetOpcode::KILL:
+  case TargetOpcode::DBG_VALUE:
+    return 0;
+  case TargetOpcode::INLINEASM:
+  case TargetOpcode::INLINEASM_BR: {
+    // TODO: Add inline ASM support.
+    return 0;
+  }
+  }
+}
+
 
 
 
@@ -163,120 +186,67 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 //                              Stack Frames
 //===----------------------------------------------------------------------===//
 
-void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 
+void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, 
                                           Register SrcReg, bool isKill, int FrameIndex, 
                                           const TargetRegisterClass *RC, Register VReg, 
                                           MachineInstr::MIFlag Flags) const {
   LLVM_DEBUG(dbgs() << "Store " << RI.getName(SrcReg) << " to slot " << FrameIndex << "\n");
-
-  MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
-  const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
-  const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
-  int64_t Offset = MFI.getObjectOffset(FrameIndex) + 
-                   MFI.getStackSize() - 
-                   TFI->getOffsetOfLocalArea();
-
-  // NOTE:  R0-based displacement instructions have a different encoding
-  //        from Rn based instructions, as such we need to know whether
-  //        we need to copy the src register into R0 temporarily.
-  Register SrcStrReg;
-  unsigned Opcode = 0;
+  
+  MachineInstr &MI = *II;
+  DebugLoc DL = MI.getDebugLoc();
   if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
-    Opcode = SH::MOVBS4;
-    SrcStrReg = SH::R0;
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVBSFR))
+        .addReg(SrcReg, getKillRegState(isKill))
+        .addFrameIndex(FrameIndex)
+        .addImm(0)
+        .addDef(SH::R0)
+        .addUse(SH::R0);
   } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
-    Opcode = SH::MOVWS4;
-    SrcStrReg = SH::R0;
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVWSFR))
+        .addReg(SrcReg, getKillRegState(isKill))
+        .addFrameIndex(FrameIndex)
+        .addImm(0)
+        .addDef(SH::R0)
+        .addUse(SH::R0);
   } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
-    Opcode = SH::MOVLS4;
-    SrcStrReg = SrcReg;
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVLSFR))
+        .addReg(SrcReg, getKillRegState(isKill))
+        .addFrameIndex(FrameIndex)
+        .addImm(0);
   } else {
-    llvm_unreachable("Cannot store this register into a stack slot!");
+    llvm_unreachable("Cannot store this register into stack slot!");
   }
-
-  // mov r14,r1
-  // add #-<frame size>,r1
-  BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SH::R1)
-    .addReg(SH::R14);
-  BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI), SH::R1)
-    .addReg(SH::R1)
-    .addImm(-(int)MFI.getStackSize());
-
-  // mov srcreg,r0
-  // mov.b/w r0,@(<offset>,r1)
-  if (SrcStrReg != SrcReg) {
-    BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SrcStrReg)
-      .addReg(SrcReg, getKillRegState(isKill));
-    BuildMI(MBB, MI, DebugLoc(), get(Opcode))
-      .addReg(SH::R1)
-      .addImm(Offset);
-    return;
-  }
-
-  // mov.l srcreg,@(<offset>,r1)
-  BuildMI(MBB, MI, DebugLoc(), get(Opcode))
-      .addReg(SrcReg, getKillRegState(isKill))
-      .addReg(SH::R1)
-      .addImm(Offset);
 }
 
-void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 
+void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, 
                                            Register DestReg, int FrameIndex, 
                                            const TargetRegisterClass *RC, Register VReg,
                                            unsigned SubReg, MachineInstr::MIFlag Flags) const {
-  MachineFunction &MF = *MBB.getParent();
-  const SuperHRegisterInfo &RI = getRegisterInfo();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
-  const SuperHTargetMachine &TM = (const SuperHTargetMachine &)MF.getTarget();
-  const TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
-  int64_t Offset = MFI.getObjectOffset(FrameIndex) + 
-                   MFI.getStackSize() - 
-                   TFI->getOffsetOfLocalArea();
-
   LLVM_DEBUG(dbgs() << "Load " << RI.getName(DestReg) << " from slot " << FrameIndex << "\n");
 
-  // NOTE:  R0-based displacement instructions have a different encoding
-  //        from Rn based instructions, as such we need to know whether
-  //        we need to copy to our dst register from R0.
-  unsigned Opcode = 0;
-  Register DstStrReg;
+  MachineInstr &MI = *II;
+  DebugLoc DL = MI.getDebugLoc();
   if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
-    Opcode = SH::MOVBL4;
-    DstStrReg = SH::R0;
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVBLFR), DestReg)
+        .addFrameIndex(FrameIndex)
+        .addImm(0)
+        .addDef(SH::R0)
+        .addUse(SH::R0);
+
   } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
-    Opcode = SH::MOVWL4;
-    DstStrReg = SH::R0;
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVWLFR), DestReg)
+        .addFrameIndex(FrameIndex)
+        .addImm(0)
+        .addDef(SH::R0)
+        .addUse(SH::R0);
+
   } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
-    Opcode = SH::MOVLL4;
-    DstStrReg = DestReg;
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVLLFR), DestReg)
+        .addFrameIndex(FrameIndex)
+        .addImm(0);
   } else {
-    llvm_unreachable("Cannot load this register into a stack slot!");
-  }
-
-  // mov r14,r1
-  // add #-<frame size>,r1
-  BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), SH::R1)
-    .addReg(SH::R14);
-  BuildMI(MBB, MI, DebugLoc(), get(SH::ADDI), SH::R1)
-    .addReg(SH::R1)
-    .addImm(-(int)MFI.getStackSize());
-
-  // mov.b/w @(<offset>,r1),r0
-  // mov r0,dstreg
-  if (DstStrReg != DestReg) {
-    BuildMI(MBB, MI, DebugLoc(), get(Opcode))
-      .addReg(SH::R1)
-      .addImm(Offset);
-    BuildMI(MBB, MI, DebugLoc(), get(SH::MOV), DestReg)
-      .addReg(DstStrReg);
-    return;
+    llvm_unreachable("Cannot load this register from stack slot!");
   }
-
-  // mov.l @(<offset>,r1),destreg
-  BuildMI(MBB, MI, DebugLoc(), get(Opcode), DestReg)
-      .addReg(SH::R1)
-      .addImm(Offset);
 }
 
 Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
@@ -365,7 +335,7 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
 
     // Handle conditional branches.
     ISD::CondCode BranchCode = getCondFromBranchOp(I->getOpcode());
-    if (BranchCode == ISD::SETFALSE) {
+    if (BranchCode == ISD::SETCC_INVALID) {
       return true; // Can't handle indirect branch.
     }
 
@@ -524,11 +494,3 @@ bool SuperHInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
   }
 }
 
-void SuperHInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
-                          MachineBasicBlock &NewDestBB,
-                          MachineBasicBlock &RestoreBB, const DebugLoc &DL,
-                          int64_t BrOffset, RegScavenger *RS) const {
-
-}
-
-
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 2a73b55410f1a..78656e8b07db9 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -48,6 +48,7 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   const MCInstrDesc &getBrCond(ISD::CondCode CC) const;
 
   // Instruction Info
+  unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
 
   /// Return the noop instruction to use for a noop.
   MCInst getNop() const override;
@@ -93,11 +94,6 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
 
   bool isBranchOffsetInRange(unsigned BranchOpc,
                              int64_t BrOffset) const override;
-
-  void insertIndirectBranch(MachineBasicBlock &MBB,
-                            MachineBasicBlock &NewDestBB,
-                            MachineBasicBlock &RestoreBB, const DebugLoc &DL,
-                            int64_t BrOffset, RegScavenger *RS) const override;
 };
 
 const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 766d6199fb376..f4fd45b1e8cd6 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -126,6 +126,18 @@ class SHRegIndirectClass<string op> : SHOpClass<"IReg" # op> {
 // Operands
 //===--------------------------------------------------------------------------===//
 
+// Operand with Scaling
+class SHScaledOp<ValueType vt, string name, int scale, bit encode = 1>
+      : Operand<vt> {
+
+  defvar Scale = !cond(!gt(scale, 0) : "<" # scale # ">", true : "");
+  defvar Suffix = Scale;
+
+  let PrintMethod = "print" # name # Suffix;
+  let EncoderMethod = !cond(encode : "get" # name # "OpValue" # Suffix, true : "");
+}
+
+
 // Immediate
 class SHImmOp<int width, ValueType vt>
       : Operand<vt>, ImmLeaf<vt, [{ return isInt<}] # width # [{>(Imm); }]> {
@@ -139,50 +151,65 @@ class SHImmOp<int width, ValueType vt>
       return false;
     }];
 }
+
 def imm8 : SHImmOp<8, i32>;
 
 // Displacement
-class SHDispOp<int width, ValueType vt>
-      : Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
-    let ParserMatchClass = SHDispClass<width>;
-    let OperandType = "OPERAND_IMMEDIATE";
-    let PrintMethod = "printDisp";
-    let MCOperandPredicate = [{
-        int64_t Imm;
-        if (MCOp.evaluateAsConstantImm(Imm))
-            return isUInt<#width>(Imm);
-        return MCOp.isBareSymbolRef();
-    }];
+class SHDispOp<int width, ValueType vt, int scale = 0>
+      : SHScaledOp<vt, "Disp", scale>, 
+        PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
+  let ParserMatchClass = SHDispClass<width>;
+  let OperandType = "OPERAND_IMMEDIATE";
+  let MCOperandPredicate = [{
+      int64_t Imm;
+      if (MCOp.evaluateAsConstantImm(Imm))
+          return isUInt<#width>(Imm);
+      return MCOp.isBareSymbolRef();
+  }];
 }
-def disp4   : SHDispOp<4, i4>;
-def disp8   : SHDispOp<8, i8>;
-def disp12  : SHDispOp<12, i16>;
 
-// PC-Relative Adressing
-class SHPCRelOp<int width, ValueType vt>
-      : Operand<vt>, PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]> {
-  let ParserMatchClass = SHPCRelClass<>;
+// Displacement
+def disp4     : SHDispOp<4,  i4,  1>;
+def disp4x2   : SHDispOp<4,  i4,  2>;
+def disp4x4   : SHDispOp<4,  i4,  4>;
+def disp8     : SHDispOp<8,  i8,  1>;
+def disp8x2   : SHDispOp<8,  i8,  2>;
+def disp8x4   : SHDispOp<8,  i8,  4>;
+def disp12    : SHDispOp<12, i16, 1>;
+
+// Memory Operand
+class SHMemriOp<RegisterClass rc, Operand dt, int scale = 0>
+      : SHScaledOp<iPTR, "Memri", scale, 0>,
+        PatLeaf<(imm), [{ return isUInt<32>(N->getSExtValue()); }]>  {
+  let OperandType = "OPERAND_MEMORY";
+  let MIOperandInfo = (ops rc, dt);
+}
+
+def memri     : SHMemriOp<GPR, i32imm,  1>;
+def memri4    : SHMemriOp<GPR, disp4,   1>;
+def memri4x2  : SHMemriOp<GPR, disp4x2, 2>;
+def memri4x4  : SHMemriOp<GPR, disp4x4, 4>;
+def memri8x2  : SHMemriOp<GPR, disp8,   2>;
+def memri8x4  : SHMemriOp<GPR, disp8,   4>;
+
+// PCRel Operand
+class SHPCRelOp<ValueType vt, int scale = 0>
+      : SHScaledOp<vt, "PCRel", scale>,
+        PatLeaf<(imm), [{ return isUInt<}] # width # [{>(N->getZExtValue()); }]>  {
   let OperandType = "OPERAND_PCREL";
-  let EncoderMethod = "getPCRelOpValue";
-  let DecoderMethod = "DecodePCRelDisp";
-  let PrintMethod = "printPCRelImm";
-    let MCOperandPredicate = [{
-        int64_t Imm;
-        if (MCOp.evaluateAsConstantImm(Imm))
-            return isUInt<#width>(Imm);
-        return MCOp.isBareSymbolRef();
-    }];
 }
 
-def pcrel8       : SHPCRelOp<8, i8>;
-def pcrel12      : SHPCRelOp<12, i16>;
+def pcrel8   : SHPCRelOp<i8>;
+def pcrel8x2 : SHPCRelOp<i8, 2>;
+def pcrel8x4 : SHPCRelOp<i8, 4>;
+def pcrel12  : SHPCRelOp<i16>;
 
 // Branch Targets
 def brtarget       : Operand<OtherVT> {
   let ParserMatchClass = SHPCRelClass<>;
   let EncoderMethod = "getBranchTargetOpValue";
   let DecoderMethod = "DecodeBranchTarget";
-  let PrintMethod = "printPCRelImm";
+  let PrintMethod = "printPCRel<1>";
   let OperandType = "OPERAND_PCREL";
 }
 
@@ -202,14 +229,6 @@ def IGPR    : SHIndirectRegOp<GPR, "">;
 def IGPRInc : SHIndirectRegOp<GPR, "Inc">;
 def IGPRDec : SHIndirectRegOp<GPR, "Dec">;
 
-// Register Indirect with Displacement @(disp,Rm)
-def memri : Operand<iPTR> {
-  let MIOperandInfo = (ops GPR, disp8);
-  let OperandType = "OPERAND_MEMORY";
-  let EncoderMethod = "getMemriOpValue";
-  let PrintMethod = "printMemri";
-}
-
 // Addressing mode pattern reg+disp
 let WantsRoot = true in
 def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
@@ -278,23 +297,23 @@ def MOVI          : InstRnI8<0b1110000000000000,
                             [(set i32:$Rn, imm:$imm)]>;
 
 // mova @(disp, PC), R0
-let hasSideEffects = 0, mayLoad = 1, Defs = [R0], isDelayIllegal = 1 in
+let hasSideEffects = 0, mayLoad = 1, Uses = [PC], Defs = [R0], isDelayIllegal = 1 in
 def MOVA          : InstD8<0b1100011100000000,
-                            (outs), (ins pcrel8:$disp),
-                            "mova $disp,r0",
-                            []>;
+                          (outs), (ins pcrel8x4:$disp),
+                          "mova $disp,r0",
+                          []>;
 
 // mov.w @(disp,PC), Rn 
-let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
+let hasSideEffects = 0, mayLoad = 1, Uses = [PC], isDelayIllegal = 1 in
 def MOVWI         : InstRnD8<0b1001000000000000,
-                            (outs GPR:$Rn), (ins pcrel8:$disp),
+                            (outs GPR:$Rn), (ins pcrel8x2:$disp),
                             "mov.w $disp,$Rn",
                             [(set i32:$Rn, (sextloadi16 constpool:$disp))]>;
 
 // mov.l @(disp,PC), Rn 
-let hasSideEffects = 0, mayLoad = 1, isDelayIllegal = 1 in
+let hasSideEffects = 0, mayLoad = 1, Uses = [PC], isDelayIllegal = 1 in
 def MOVLI         : InstRnD8<0b1101000000000000,
-                            (outs GPR:$Rn), (ins pcrel8:$disp),
+                            (outs GPR:$Rn), (ins pcrel8x4:$disp),
                             "mov.l $disp,$Rn",
                             [(set i32:$Rn, (load constpool:$disp))]>;
 
@@ -333,19 +352,19 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
   def MOVBL             : InstRmRn<0b0110000000000000,
                                   (outs GPR:$Rn), (ins IGPR:$Rm),
                                   "mov.b $Rm,$Rn",
-                                  [(set i32:$Rn, (sextloadi8 IGPR:$Rm))]>;
+                                  []>;
 
   // mov.w @Rm, Rn
   def MOVWL             : InstRmRn<0b0110000000000001,
                                   (outs GPR:$Rn), (ins IGPR:$Rm),
                                   "mov.w $Rm,$Rn",
-                                  [(set i32:$Rn, (sextloadi16 IGPR:$Rm))]>;
+                                  []>;
 
   // mov.l @Rm, Rn
   def MOVLL             : InstRmRn<0b0110000000000010,
                                   (outs GPR:$Rn), (ins IGPR:$Rm),
                                   "mov.l $Rm,$Rn",
-                                  [(set i32:$Rn, (load IGPR:$Rm))]>;
+                                  []>;
 
   // mov.b @Rm+, Rn
   let isDelayIllegal = 1 in
@@ -371,22 +390,22 @@ let hasSideEffects = 0, mayLoad = 1, isReMaterializable = 1 in {
   // mov.b @(disp, Rm), R0
   let Defs = [R0] in
   def MOVBL4            : InstRmD4<0b1000010000000000,
-                                  (outs), (ins (memri $Rm, $disp):$src),
+                                  (outs), (ins (memri4 $Rm, $disp):$src),
                                   "mov.b $src,R0",
-                                  [(set R0, (sextloadi8 addr:$src))]>;
+                                  []>;
   
   // mov.w @(disp, Rm), R0
   let Defs = [R0] in
   def MOVWL4            : InstRmD4<0b1000010100000000,
-                                  (outs), (ins (memri $Rm, $disp):$src),
+                                  (outs), (ins (memri4x2 $Rm, $disp):$src),
                                   "mov.w $src,R0",
-                                  [(set R0, (sextloadi16 addr:$src))]>;
+                                  []>;
   
   // mov.l @(disp, Rm), Rn
   def MOVLL4          : InstRmRnD4<0b0101000000000000,
-                                  (outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                                  (outs GPR:$Rn), (ins (memri4x4 $Rm, $disp):$src),
                                   "mov.l $src,$Rn",
-                                  [(set i32:$Rn, (load addr:$src))]>;
+                                  []>;
 
   // mov.b @(R0,Rm),Rn
   let Uses = [R0] in
@@ -444,19 +463,19 @@ let hasSideEffects = 0, mayStore = 1 in {
   def MOVBS             : InstRmRn<0b0010000000000000,
                                   (outs), (ins GPR:$Rm, IGPR:$Rn),
                                   "mov.b $Rm,$Rn",
-                                  [(truncstorei8 i32:$Rm, i32:$Rn)]>;
+                                  []>;
 
   // mov.w Rm, @Rn
   def MOVWS             : InstRmRn<0b0010000000000001,
                                   (outs), (ins GPR:$Rm, IGPR:$Rn),
                                   "mov.w $Rm,$Rn",
-                                  [(truncstorei16 i32:$Rm, i32:$Rn)]>;
+                                  []>;
 
   // mov.l Rm, @Rn
   def MOVLS             : InstRmRn<0b0010000000000010,
                                   (outs), (ins GPR:$Rm, IGPR:$Rn),
                                   "mov.l $Rm,$Rn",
-                                  [/*(store i32:$Rm, i32:$Rn)*/]>;
+                                  []>;
 
   // mov.b Rm, @-Rn
   let isDelayIllegal = 1 in
@@ -482,22 +501,22 @@ let hasSideEffects = 0, mayStore = 1 in {
   // mov.b R0, @(disp, Rn)
   let Uses = [R0] in
   def MOVBS4            : InstRnD4<0b1000000000000000,
-                                  (outs), (ins (memri $Rn, $disp):$dst),
+                                  (outs), (ins (memri4 $Rn, $disp):$dst),
                                   "mov.b r0,$dst",
-                                  [/*(truncstorei8 i32, addr:$dst)*/]>;
+                                  []>;
   
   // mov.w R0, @(disp, Rn)
   let Uses = [R0] in
   def MOVWS4            : InstRnD4<0b1000000100000000,
-                                  (outs), (ins (memri $Rn, $disp):$dst),
+                                  (outs), (ins (memri4x2 $Rn, $disp):$dst),
                                   "mov.w r0,$dst",
-                                  [/*(truncstorei16 i32, addr:$dst)*/]>;
+                                  []>;
   
   // mov.l Rm, @(disp, Rn)
   def MOVLS4          : InstRmRnD4<0b0001000000000000,
-                                  (outs), (ins GPR:$Rm, (memri $Rn, $disp):$dst),
+                                  (outs), (ins GPR:$Rm, (memri4x4 $Rn, $disp):$dst),
                                   "mov.l $Rm,$dst",
-                                  [(store i32:$Rm, addr:$dst)]>;
+                                  []>;
 
   // mov.b Rm,@(R0,Rn)
   let Uses = [R0] in
@@ -1380,14 +1399,6 @@ def : Pat<(sext_inreg i32:$src, i1),  (EXTSB i32:$src)>;
 def : Pat<(sext_inreg i32:$src, i8),  (EXTSB i32:$src)>;
 def : Pat<(sext_inreg i32:$src, i16), (EXTSW i32:$src)>;
 
-//===--------------------------------------------------------------------------===//
-// Truncating Store
-//===--------------------------------------------------------------------------===//
-
-// def : Pat<(truncstorei8  i32:$src, i32:$dst), (MOVBRmRni i32:$src, i32:$dst)>;
-// def : Pat<(truncstorei16 i32:$src, i32:$dst), (MOVWRmRni i32:$src, i32:$dst)>;
-
-
 
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
@@ -1417,6 +1428,36 @@ def Select32    : SHSelectPseudo<(outs GPR:$dst),
                                 [(set i32:$dst,
                                  (SHselectcc i32:$src, i32:$src2, imm:$cc))]>;
 
+//===--------------------------------------------------------------------------===//
+// Frame Load/Store
+//===--------------------------------------------------------------------------===//
+
+// LOAD FROM FRAME
+def MOVBLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                          "! MOVBLFR $src, $Rn",
+                          [(set i32:$Rn, (extloadi8 addr:$src))]>;
+
+def MOVWLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                          "! MOVWLFR $src, $Rn",
+                          [(set i32:$Rn, (extloadi16 addr:$src))]>;
+
+def MOVLLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                          "! MOVLLFR $src, $Rn",
+                          [(set i32:$Rn, (load addr:$src))]>;
+
+// STORE TO FRAME
+def MOVBSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                           "! MOVBSFR $src, $dst",
+                           [(truncstorei8 i32:$src, addr:$dst)]>;
+
+def MOVWSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                           "! MOVWSFR $src, $dst",
+                           [(truncstorei16 i32:$src, addr:$dst)]>;
+
+def MOVLSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                           "! MOVLSFR $src, $dst",
+                           [(store i32:$src, addr:$dst)]>;
+
 //===--------------------------------------------------------------------------===//
 // Stack Frame
 //===--------------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index 79451cd815e4a..d64518bac837f 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -65,6 +65,7 @@ void SuperHMCInstLower::lowerInstruction(const MachineInstr &MI,
       // Ignore all implicit register operands.
       if (MO.isImplicit())
         continue;
+
       MCOp = MCOperand::createReg(MO.getReg());
       break;
     case MachineOperand::MO_Immediate:
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 86867e04273b2..a1ed734beedb1 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -23,6 +23,9 @@
 #include "llvm/CodeGen/RegisterScavenging.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include <cstdint>
 
 using namespace llvm;
 
@@ -71,61 +74,26 @@ SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
 
 BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   BitVector Reserved(getNumRegs());
+  const SuperHFrameLowering *FR = getFrameLowering(MF);
 
   // R0 is always reserved as some instructions can only write to it.
   Reserved.set(SH::R0);
-
-  // Reserve GOT pointer
-  Reserved.set(SH::R12);
   
-  // Also reserve the stack frame and stack pointer.
-  Reserved.set(SH::R14);
+  // R1 is generally used as the temporary storage for addresses.
+  Reserved.set(SH::R1);
+  
+  // Also reserve the stack pointer.
   Reserved.set(SH::R15);
 
-  // Status Register
-  Reserved.set(SH::SR);
-  return Reserved;
-}
-
-/// getLoadBaseOffset - Gets the base offset to emit a load/store from.
-static int64_t getLoadStoreBaseOffset(unsigned Opcode) {
-  switch(Opcode) {
-  case SH::MOVBL4:
-  case SH::MOVBS4:
-    return 12;
-
-  case SH::MOVWL4:
-  case SH::MOVWS4:
-    return 28;
-
-  case SH::MOVLS4:
-  case SH::MOVLL4:
-    return 60;
-
-  default:
-    return 0;
-  }
-}
-
-/// getLoadBaseOffset - Gets the neccesary bit shift amount for the
-/// load/store indexing
-static int64_t getLoadStoreOffsetShift(unsigned Opcode) {
-  switch(Opcode) {
-  case SH::MOVBL4:
-  case SH::MOVBS4:
-    return 0;
-
-  case SH::MOVWL4:
-  case SH::MOVWS4:
-    return 1;
+  // Reserve GOT pointer
+  if (Subtarget.isPositionIndependent())
+    Reserved.set(SH::R12);
 
-  case SH::MOVLS4:
-  case SH::MOVLL4:
-    return 2;
+  // Reserver frame pointer if it's used.
+  if (FR->hasFP(MF))
+    Reserved.set(SH::R14);
 
-  default:
-    return 0;
-  }
+  return Reserved;
 }
 
 static void replaceFI(const MachineFunction &MF, MachineBasicBlock::iterator II,
@@ -153,94 +121,13 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   // Get the register offset to fetch.
   Register FrameReg;
   int64_t Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
-  int64_t ROff = getLoadStoreBaseOffset(MI.getOpcode());
-  int64_t Shift = getLoadStoreOffsetShift(MI.getOpcode());
-
-  // Handle frame loads and stores.
-  switch(MI.getOpcode()) {
-
-  // Stack Store
-  case SH::MOVBS4:
-  case SH::MOVWS4: {
-    Register SrcReg = MI.getOperand(0).getReg();
-    
-    // Expand sequence to
-    // mov      <base reg>,r1
-    // add      #-ROff,r1
-    // mov      <src reg>, r0
-    // mov.w/b  r0,@(ROff+Offset,r1)
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
-      .addReg(FrameReg);
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
-      .addReg(SH::R1)
-      .addImm(-ROff);
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R0)
-      .addReg(SrcReg);
-
-    Offset = (ROff-Offset) >> Shift;
-    FrameReg = SH::R1;
-    break;
-  }
-  case SH::MOVLS4: {
-
-    // Expand sequence to
-    // mov      <base reg>,r1
-    // add      #-ROff,r1
-    // mov.l    <src reg>,@(ROff+Offset,r1)
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
-      .addReg(FrameReg);
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
-      .addReg(SH::R1)
-      .addImm(-ROff);
-
-    Offset = (ROff-Offset) >> Shift;
-    FrameReg = SH::R1;
-    break;
-  }
-
-  // Stack Load
-  case SH::MOVBL4:
-  case SH::MOVWL4: {
-    Register DstReg = MI.getOperand(0).getReg();
-
-    // Expand sequence to
-    // mov      <base reg>,r1
-    // add      #-ROff,r1
-    // mov.w/b  @(ROff+Offset,r1),r0
-    // mov      r0,<dst reg>
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
-      .addReg(FrameReg);
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
-      .addReg(SH::R1)
-      .addImm(-ROff);
-
-    // This inserts it after our instruction
-    BuildMI(*MI.getParent(), MI, DL, TII.get(SH::ADDI), DstReg)
-      .addReg(SH::R0)
-      .addImm(-ROff);
-
-    Offset = (ROff-Offset) >> Shift;
-    FrameReg = SH::R1;
-    break;
-  }
-  case SH::MOVLL4: {
-
-    // Expand sequence to
-    // mov    <base reg>,r1
-    // add    #-ROff,r1
-    // mov.l  @(ROff+Offset,r1),<dst reg>
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::MOV), SH::R1)
-      .addReg(FrameReg);
-    BuildMI(*MI.getParent(), II, DL, TII.get(SH::ADDI), SH::R1)
-      .addReg(SH::R1)
-      .addImm(-ROff);
-
-    Offset = (ROff-Offset) >> Shift;
-    FrameReg = SH::R1;
-    break;
-  }
-  }
 
+  LLVM_DEBUG({
+    int64_t Fo = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
+    dbgs()  << "Eliminiate FI " << FrameIndex << " @ SP["
+            << -Fo << "]...\n";
+  });
+  
   replaceFI(MF, II, MI, DL, FIOperandNum, Offset, FrameReg);
   return false;
 }
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index 0a69b4b9a8c2c..1c7c1f52fea51 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -36,6 +36,7 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
   const TargetRegisterClass *getLargestLegalSuperClass(const TargetRegisterClass *RC,
                                            const MachineFunction &MF) const override;
   Register getFrameRegister(const MachineFunction &MF) const override;
+
   bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
                            unsigned FIOperandNum,
                            RegScavenger *RS = nullptr) const override;
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 3118603fe51d0..18dd3cfc1e7e0 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -32,6 +32,7 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSuperHTarget() {
 
   PassRegistry &Registry = *PassRegistry::getPassRegistry();
   initializeSuperHAsmPrinterPass(Registry);
+  initializeSuperHExpandPseudoPass(Registry);
   initializeSuperHFillDelaySlotsPass(Registry);
   initializeSuperHConstantIslandsPass(Registry);
   initializeSuperHDAGToDAGISelLegacyPass(Registry);
@@ -48,6 +49,7 @@ class SuperHPassConfig : public TargetPassConfig {
     : TargetPassConfig(TM, PM) {}
 
   bool addInstSelector() override;
+  void addPreSched2() override;
   void addPreEmitPass2() override;
   SuperHTargetMachine &getSuperHTargetMachine() const {
     return getTM<SuperHTargetMachine>();
@@ -59,7 +61,11 @@ bool SuperHPassConfig::addInstSelector() {
   return false;
 }
 
+void SuperHPassConfig::addPreSched2() {
+}
+
 void SuperHPassConfig::addPreEmitPass2() {
+  addPass(createSuperHExpandPseudoPass());
   addPass(createSuperHFillDelaySlotsPass());
 
   // Inserts Constant Islands. Block sizes cannot be increased after this point,

>From 35278af66957847e56959d4a2fb3d3fb17f4b75d Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 6 Sep 2026 16:25:26 +0200
Subject: [PATCH 40/67] Half-reimplement 8-16 bit loads/stores

---
 .../Target/SuperH/SuperHFillDelaySlots.cpp    | 17 ++++--
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 45 ++++++++++++---
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |  5 ++
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 56 +++++++++----------
 4 files changed, 79 insertions(+), 44 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index 5fd82e22c68bc..a35a0a82ec252 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -70,12 +70,16 @@ MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI)
   MachineInstr &MI = *MBBI;
   auto *Prev = MBBI->getPrevNode();
 
-  // We might have a useful instruction above the instruction that
-  // loads our destination address.
-  if (MI.isCall() && Prev) {
-    if (!Prev->getPrevNode()->definesRegister(MI.getOperand(0).getReg(), TRI))
-      Prev = Prev->getPrevNode();
-  }
+  // Instructions that fall through should not get their delay slots filled.
+  if (MBB.getLastNonDebugInstr() == MBBI)
+    return nullptr;
+
+  // // We might have a useful instruction above the instruction that
+  // // loads our destination address.
+  // if (MI.isCall() && Prev) {
+  //   if (!Prev->getPrevNode()->definesRegister(MI.getOperand(0).getReg(), TRI))
+  //     Prev = Prev->getPrevNode();
+  // }
 
   // TODO:  Make this a while loop that keeps a list of "used" registers
   //        by instructions.
@@ -151,6 +155,7 @@ bool SuperHFillDelaySlots::expandMI(Block &MBB, BlockIt MBBI) {
   if (MI.hasDelaySlot()) {
     return fillDelaySlot(MBB, MBBI);
   }
+
   return false;
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index e1ed74ae00814..4a86a4e4fc0d1 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -98,7 +98,10 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
   setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
-  setOperationAction(ISD::Constant, MVT::i32, Custom);
+  
+  for (MVT VT : MVT::integer_valuetypes()) {
+    setOperationAction(ISD::Constant, VT, Custom);
+  }
 
   setOperationAction(ISD::BR_CC, MVT::i8, Custom);
   setOperationAction(ISD::BR_CC, MVT::i16, Custom);
@@ -115,10 +118,6 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::SETCC, MVT::i32, Custom);
   setOperationAction(ISD::SETCC, MVT::i64, Custom);
 
-  // for (MVT VT : MVT::integer_valuetypes()) {
-  //   setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Expand);
-  // }
-
   setBooleanContents(ZeroOrOneBooleanContent);
   setBooleanVectorContents(ZeroOrOneBooleanContent);
   setJumpIsExpensive(false);
@@ -193,6 +192,38 @@ SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
 
 
 
+//===----------------------------------------------------------------------===//
+//                              TYPE LOWERING
+//===----------------------------------------------------------------------===//
+
+void 
+SuperHTargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, 
+                                         SelectionDAG &DAG) const {
+  DEBUG_FN_PRINT()
+
+  SDLoc DL(N);
+
+  switch (N->getOpcode()) {
+  case ISD::Constant: {
+    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
+      Results.push_back(DAG.getConstant(C->getSExtValue(), DL, MVT::i32));
+    }
+    break;
+  }
+  default: {
+    SDValue Res = LowerOperation(SDValue(N, 0), DAG);
+
+    for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I)
+      Results.push_back(Res.getValue(I));
+
+    break;
+  }
+  }
+}
+
+
+
+
 //===----------------------------------------------------------------------===//
 //                            CONSTANT LOWERING
 //===----------------------------------------------------------------------===//
@@ -693,12 +724,12 @@ SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
     llvm_unreachable("Unexpected type for ");
 
   case MVT::i8: {
-    MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+    MachineSDNode *MUL = DAG.getMachineNode(SH::MULU, DL, VT, Op.getOperand(0), Op.getOperand(1));
     return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
   }
 
   case MVT::i16: {
-    MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+    MachineSDNode *MUL = DAG.getMachineNode(SH::MULS, DL, VT, Op.getOperand(0), Op.getOperand(1));
     return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
   }
 
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 0d73e0749958d..7b6a9d88006b5 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -30,6 +30,11 @@ class SuperHTargetLowering : public TargetLowering  {
 public:
   SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
 
+  /// ReplaceNodeResults - Replace a node with an illegal result type
+  /// with a new node built out of custom code.
+  void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
+                                           SelectionDAG &DAG) const override;
+
   // LowerToConstantPool - SuperH's compressed instruction set means that 
   // immediates and displacements can not be larger than 8 bits. 
   // As such we need to store said immediates and displacements within 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index f4fd45b1e8cd6..07eb5f95ee1fb 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -1372,34 +1372,6 @@ def TRAPA             : InstI8<0b1100001100000000,
 include "SuperHInstrDSP.td"
 
 
-
-
-
-//===--------------------------------------------------------------------------===//
-//===--------------------------------------------------------------------------===//
-//                            Non-Instruction Patterns
-//===--------------------------------------------------------------------------===//
-//===--------------------------------------------------------------------------===//
-
-//===--------------------------------------------------------------------------===//
-// Zero-Extend Load
-//===--------------------------------------------------------------------------===//
-
-// def : Pat<(i32 (zextloadi1  i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
-// def : Pat<(i32 (zextloadi8  i32:$src)), (EXTUBRmRn (MOVBRmiRn i32:$src))>;
-// def : Pat<(i32 (zextloadi16 i32:$src)), (EXTUWRmRn (MOVWRmiRn i32:$src))>;
-// def : Pat<(i32 (extloadi1   i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
-// def : Pat<(i32 (extloadi8   i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
-// def : Pat<(i32 (extloadi16  i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
-// def : Pat<(i32 (sextloadi1  i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
-// def : Pat<(i32 (sextloadi8  i32:$src)), (EXTSBRmRn (MOVBRmiRn i32:$src))>;
-// def : Pat<(i32 (sextloadi16 i32:$src)), (EXTSWRmRn (MOVWRmiRn i32:$src))>;
-
-def : Pat<(sext_inreg i32:$src, i1),  (EXTSB i32:$src)>;
-def : Pat<(sext_inreg i32:$src, i8),  (EXTSB i32:$src)>;
-def : Pat<(sext_inreg i32:$src, i16), (EXTSW i32:$src)>;
-
-
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 //                              Pseudo instructions
@@ -1435,11 +1407,11 @@ def Select32    : SHSelectPseudo<(outs GPR:$dst),
 // LOAD FROM FRAME
 def MOVBLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                           "! MOVBLFR $src, $Rn",
-                          [(set i32:$Rn, (extloadi8 addr:$src))]>;
+                          [(set i32:$Rn, (sextloadi8 addr:$src))]>;
 
 def MOVWLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                           "! MOVWLFR $src, $Rn",
-                          [(set i32:$Rn, (extloadi16 addr:$src))]>;
+                          [(set i32:$Rn, (sextloadi16 addr:$src))]>;
 
 def MOVLLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                           "! MOVLLFR $src, $Rn",
@@ -1483,4 +1455,26 @@ def ADJCALLSTACKDOWN : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
 def ADJCALLSTACKUP : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
                             "!ADJCALLSTACKUP $amt1",
                             [(SHCallSeqEnd timm:$amt1, timm:$amt2)]>;
-}
\ No newline at end of file
+}
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                            Non-Instruction Patterns
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+//===--------------------------------------------------------------------------===//
+// Zero-Extend Load
+//===--------------------------------------------------------------------------===//
+
+def : Pat<(i32 (sextloadi1  addr:$src)), (MOVBLFR addr:$src)>;
+def : Pat<(i32 (zextloadi1  addr:$src)), (EXTUB (MOVBLFR addr:$src))>;
+def : Pat<(i32 (zextloadi8  addr:$src)), (EXTUB (MOVBLFR addr:$src))>;
+def : Pat<(i32 (zextloadi16 addr:$src)), (EXTUW (MOVWLFR addr:$src))>;
+
+def : Pat<(sext_inreg i32:$src, i1),  (EXTSB i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i8),  (EXTSB i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i16), (EXTSW i32:$src)>;
\ No newline at end of file

>From 806460613804a121b42c1c7612caa796a1b6827a Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 8 Sep 2026 09:43:17 +0200
Subject: [PATCH 41/67] More refactoring

---
 llvm/lib/Target/SuperH/README.txt             |  1 -
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 83 +++++++++++++------
 .../lib/Target/SuperH/SuperHFrameLowering.cpp | 17 ++--
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp |  6 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 62 ++++++++------
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 16 +++-
 6 files changed, 117 insertions(+), 68 deletions(-)

diff --git a/llvm/lib/Target/SuperH/README.txt b/llvm/lib/Target/SuperH/README.txt
index 6c34f247541fc..d296a4566ddb8 100644
--- a/llvm/lib/Target/SuperH/README.txt
+++ b/llvm/lib/Target/SuperH/README.txt
@@ -13,6 +13,5 @@
 //===---------------------------------------------------------------------===//
 
   * Only SH2 level codegen is implemented.
-  * O1 compilation fails due to misgenerated fallthrough MBBs
   * 64-bit integers are not handled.
   * Varargs are not implemented.
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index 5daf40e32f1d7..c09b79239dda4 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -27,6 +27,12 @@ using namespace llvm;
 #define DEBUG_TYPE "sh-expand-pseudo"
 #define SH_EXPAND_PSEUDO_NAME "SH pseudo instruction expansion pass"
 
+#ifndef NDEBUG
+static cl::opt<bool>
+CNoExpand("sh-no-expand", cl::Hidden, cl::init(false),
+          cl::desc("Force the backend to not expand instructions."));
+#endif
+
 namespace {
 class SuperHExpandPseudo : public MachineFunctionPass {
 public:
@@ -83,11 +89,15 @@ bool SuperHExpandPseudo::expand<SH::MOVBSFR>(Block &MBB, BlockIt MBBI) {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   auto SrcReg = MI.getOperand(0).getReg();
+  bool SrcIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
   int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 1);
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVBSFR to MOVBS4...\n");
+  LLVM_DEBUG(dbgs() << "Expanding MOVBSFR to MOVBS4 @"
+                    << " spoffset=" << SpOffset 
+                    << " offset=" << SpOffset-Offset 
+                    <<  "...\n");
 
   // Expand sequence to
   // mov      <base reg>,r1
@@ -100,9 +110,9 @@ bool SuperHExpandPseudo::expand<SH::MOVBSFR>(Block &MBB, BlockIt MBBI) {
     .addReg(SH::R1)
     .addImm(-SpOffset);
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
-    .addReg(SrcReg);
+    .addReg(SrcReg, getKillRegState(SrcIsKill));
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS4))
-    .addReg(SH::R1)
+    .addReg(SH::R1, RegState::Kill)
     .addImm(SpOffset-Offset);
   MI.eraseFromParent();
   return true;
@@ -116,11 +126,15 @@ bool SuperHExpandPseudo::expand<SH::MOVWSFR>(Block &MBB, BlockIt MBBI) {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   auto SrcReg = MI.getOperand(0).getReg();
+  bool SrcIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
   int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 2);
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVWSFR to MOVWS4...\n");
+  LLVM_DEBUG(dbgs() << "Expanding MOVWSFR to MOVWS4 @"
+                    << " spoffset=" << SpOffset 
+                    << " offset=" << SpOffset-Offset 
+                    <<  "...\n");
 
   // Expand sequence to
   // mov      <base reg>,r1
@@ -133,9 +147,9 @@ bool SuperHExpandPseudo::expand<SH::MOVWSFR>(Block &MBB, BlockIt MBBI) {
     .addReg(SH::R1)
     .addImm(-SpOffset);
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
-    .addReg(SrcReg);
+    .addReg(SrcReg, getKillRegState(SrcIsKill));
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS4))
-    .addReg(SH::R1)
+    .addReg(SH::R1, RegState::Kill)
     .addImm(SpOffset-Offset);
   MI.eraseFromParent();
   return true;
@@ -149,11 +163,15 @@ bool SuperHExpandPseudo::expand<SH::MOVLSFR>(Block &MBB, BlockIt MBBI) {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   auto SrcReg = MI.getOperand(0).getReg();
+  bool SrcIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
   int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 4);
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVLSFR to MOVLS4...\n");
+  LLVM_DEBUG(dbgs() << "Expanding MOVLSFR to MOVLS4 @"
+                    << " spoffset=" << SpOffset 
+                    << " offset=" << SpOffset-Offset 
+                    <<  "...\n");
     
   // Expand sequence to
   // mov      <base reg>,r1
@@ -165,8 +183,8 @@ bool SuperHExpandPseudo::expand<SH::MOVLSFR>(Block &MBB, BlockIt MBBI) {
     .addReg(SH::R1)
     .addImm(-SpOffset);
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
-    .addReg(SrcReg)
-    .addReg(SH::R1)
+    .addReg(SrcReg, getKillRegState(SrcIsKill))
+    .addReg(SH::R1, RegState::Kill)
     .addImm(SpOffset-Offset);
   MI.eraseFromParent();
   return true;
@@ -186,16 +204,16 @@ bool SuperHExpandPseudo::expand<SH::MOVBLFR>(Block &MBB, BlockIt MBBI) {
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVBLFR to MOVBL4...\n");
-
   auto DstReg = MI.getOperand(0).getReg();
+  bool DstIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
   int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 1);
 
-  // HACK:  Need to find a better way of handling this, it's likely to break.
-  MBBI = std::next(MBBI);
-  MBBI = std::next(MBBI);
+  LLVM_DEBUG(dbgs() << "Expanding MOVBLFR to MOVBL4 @"
+                    << " spoffset=" << SpOffset 
+                    << " offset=" << SpOffset-Offset 
+                    <<  "...\n");
     
   // Expand sequence to
   // mov      <base reg>,r1
@@ -209,9 +227,11 @@ bool SuperHExpandPseudo::expand<SH::MOVBLFR>(Block &MBB, BlockIt MBBI) {
     .addImm(-SpOffset);
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL4))
     .addReg(SH::R1)
-    .addImm(SpOffset-Offset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), DstReg)
-    .addReg(SH::R0);
+    .addImm(SpOffset-Offset)
+    .addReg(SH::R0, RegState::Define);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
+    .addReg(DstReg, getKillRegState(DstIsKill))
+    .addReg(SH::R0, RegState::Kill);
   MI.eraseFromParent();
   return true;
 }
@@ -223,16 +243,16 @@ bool SuperHExpandPseudo::expand<SH::MOVWLFR>(Block &MBB, BlockIt MBBI) {
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVWLFR to MOVWL4...\n");
-
   auto DstReg = MI.getOperand(0).getReg();
+  bool DstIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
   int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 2);
 
-  // HACK:  Need to find a better way of handling this, it's likely to break.
-  MBBI = std::next(MBBI);
-  MBBI = std::next(MBBI);
+  LLVM_DEBUG(dbgs() << "Expanding MOVWLFR to MOVWL4 @"
+                    << " spoffset=" << SpOffset 
+                    << " offset=" << SpOffset-Offset 
+                    <<  "...\n");
     
   // Expand sequence to
   // mov      <base reg>,r1
@@ -247,8 +267,9 @@ bool SuperHExpandPseudo::expand<SH::MOVWLFR>(Block &MBB, BlockIt MBBI) {
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4))
     .addReg(SH::R1)
     .addImm(SpOffset-Offset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), DstReg)
-    .addReg(SH::R0);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
+    .addReg(DstReg, getKillRegState(DstIsKill))
+    .addReg(SH::R0, RegState::Define);
   MI.eraseFromParent();
   return true;
 }
@@ -261,11 +282,15 @@ bool SuperHExpandPseudo::expand<SH::MOVLLFR>(Block &MBB, BlockIt MBBI) {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   auto DstReg = MI.getOperand(0).getReg();
+  bool DstIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
   int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 4);
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVLLFR to MOVLL4...\n");
+  LLVM_DEBUG(dbgs() << "Expanding MOVLLFR to MOVLL4 @"
+                    << " spoffset=" << SpOffset 
+                    << " offset=" << SpOffset-Offset 
+                    <<  "...\n");
     
   // Expand sequence to
   // mov      <base reg>,r1
@@ -276,7 +301,8 @@ bool SuperHExpandPseudo::expand<SH::MOVLLFR>(Block &MBB, BlockIt MBBI) {
   BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
     .addReg(SH::R1)
     .addImm(-SpOffset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4), DstReg)
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4))
+    .addReg(DstReg, getKillRegState(DstIsKill))
     .addReg(SH::R1)
     .addImm(SpOffset-Offset);
   MI.eraseFromParent();
@@ -305,6 +331,11 @@ bool SuperHExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
 bool SuperHExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
   bool Modified = false;
 
+  #ifndef NDEBUG
+  if (CNoExpand)
+    return false;
+  #endif
+
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   TRI = STI.getRegisterInfo();
   TII = STI.getInstrInfo();
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index db3b35cb06a8d..8ecd1d9a753f5 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -61,14 +61,6 @@ static unsigned getShiftAmt(uint32_t Val) {
   return R;
 }
 
-/// adjustFrameOffsetDown - Helper that adjusts frame offset
-/// down. 
-static void adjustFrameOffsetDown(int64_t &FrameOffset) {
-  FrameOffset -= 4;
-  if (FrameOffset < 0)
-    FrameOffset = 0;
-}
-
 // Helper to emit stack pointer adjustment.
 void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB, 
                                           MachineBasicBlock::iterator MBBI, int32_t AdjValue) const {
@@ -144,7 +136,8 @@ SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
 
   // NOTE:  All the frame indices are relative to the stack/frame pointer
   //        post-offset. as such an extra adjustment is needed here.
-  int64_t FrameOffset = MFI.getObjectOffset(FI);
+  int64_t FrameOffset = MFI.getObjectOffset(FI)+1;
+
 
   // R14 base
   if (HasFP) {
@@ -181,8 +174,12 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
   bool HasFP = hasFP(MF);
 
-  // Get stack frame size.
+  // Get stack frame size, align up to 32-bits if needed.
   int64_t StackSize = MFI.getStackSize();
+  if (StackSize < 4)
+    StackSize = 4;
+
+  MFI.setStackSize(StackSize);
 
   // Store previous frame pointer.
   if (HasFP) {
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 4a86a4e4fc0d1..9f8da36d6c795 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -68,16 +68,20 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
 
   setSchedulingPreference(Sched::RegPressure);
   setSupportsUnalignedAtomics(false);
-  // setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
+  setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
 
   // Loads and stores are legal
   for (MVT VT : MVT::integer_valuetypes()) {
     for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
       setLoadExtAction(N, VT, MVT::i1, Promote);
+      // setLoadExtAction(N, VT, MVT::i8, Expand);
+      // setLoadExtAction(N, VT, MVT::i16, Expand);
       setLoadExtAction(N, VT, MVT::i64, Expand);
     }
 
     setTruncStoreAction(VT, MVT::i1, Promote);
+    // setTruncStoreAction(VT, MVT::i8, Expand);
+    // setTruncStoreAction(VT, MVT::i16, Expand);
   }
 
   // Division and remainders are multi-instruction sequences
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 94bc9ceade1cc..7f8095d0a3a73 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -190,29 +190,32 @@ void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBl
                                           Register SrcReg, bool isKill, int FrameIndex, 
                                           const TargetRegisterClass *RC, Register VReg, 
                                           MachineInstr::MIFlag Flags) const {
-  LLVM_DEBUG(dbgs() << "Store " << RI.getName(SrcReg) << " to slot " << FrameIndex << "\n");
-  
+
   MachineInstr &MI = *II;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  uint ObjectSize = MFI.getObjectSize(FrameIndex);
   DebugLoc DL = MI.getDebugLoc();
+
+  LLVM_DEBUG(dbgs() << "Store " << RI.getName(SrcReg) 
+                    << " to slot " << FrameIndex
+                    << " size=" << ObjectSize << "\n");
+
   if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVBSFR))
-        .addReg(SrcReg, getKillRegState(isKill))
-        .addFrameIndex(FrameIndex)
-        .addImm(0)
-        .addDef(SH::R0)
-        .addUse(SH::R0);
+      .addReg(SrcReg, getKillRegState(isKill))
+      .addFrameIndex(FrameIndex)
+      .addImm(0);
   } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVWSFR))
-        .addReg(SrcReg, getKillRegState(isKill))
-        .addFrameIndex(FrameIndex)
-        .addImm(0)
-        .addDef(SH::R0)
-        .addUse(SH::R0);
+      .addReg(SrcReg, getKillRegState(isKill))
+      .addFrameIndex(FrameIndex)
+      .addImm(0);
   } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVLSFR))
-        .addReg(SrcReg, getKillRegState(isKill))
-        .addFrameIndex(FrameIndex)
-        .addImm(0);
+      .addReg(SrcReg, getKillRegState(isKill))
+      .addFrameIndex(FrameIndex)
+      .addImm(0);
   } else {
     llvm_unreachable("Cannot store this register into stack slot!");
   }
@@ -222,28 +225,35 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
                                            Register DestReg, int FrameIndex, 
                                            const TargetRegisterClass *RC, Register VReg,
                                            unsigned SubReg, MachineInstr::MIFlag Flags) const {
-  LLVM_DEBUG(dbgs() << "Load " << RI.getName(DestReg) << " from slot " << FrameIndex << "\n");
 
   MachineInstr &MI = *II;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  uint ObjectSize = MFI.getObjectSize(FrameIndex);
   DebugLoc DL = MI.getDebugLoc();
+
+  // HACK: This is ugly but it works.. somehow.
+  II = std::next(II);
+  II = std::next(II);
+
+  LLVM_DEBUG(dbgs() << "Load " << RI.getName(DestReg) 
+                    << " from slot " << FrameIndex
+                    << " size=" << ObjectSize << "\n");
+
   if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVBLFR), DestReg)
-        .addFrameIndex(FrameIndex)
-        .addImm(0)
-        .addDef(SH::R0)
-        .addUse(SH::R0);
+      .addFrameIndex(FrameIndex)
+      .addImm(0);
 
   } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVWLFR), DestReg)
-        .addFrameIndex(FrameIndex)
-        .addImm(0)
-        .addDef(SH::R0)
-        .addUse(SH::R0);
+      .addFrameIndex(FrameIndex)
+      .addImm(0);
 
   } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVLLFR), DestReg)
-        .addFrameIndex(FrameIndex)
-        .addImm(0);
+      .addFrameIndex(FrameIndex)
+      .addImm(0);
   } else {
     llvm_unreachable("Cannot load this register from stack slot!");
   }
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 07eb5f95ee1fb..87494648e3102 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -1405,19 +1405,23 @@ def Select32    : SHSelectPseudo<(outs GPR:$dst),
 //===--------------------------------------------------------------------------===//
 
 // LOAD FROM FRAME
+let mayLoad = 1, Defs = [R0, R1], Uses = [R0, R1] in {
 def MOVBLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                           "! MOVBLFR $src, $Rn",
-                          [(set i32:$Rn, (sextloadi8 addr:$src))]>;
+                          []>;
 
 def MOVWLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                           "! MOVWLFR $src, $Rn",
-                          [(set i32:$Rn, (sextloadi16 addr:$src))]>;
+                          []>;
 
 def MOVLLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                           "! MOVLLFR $src, $Rn",
-                          [(set i32:$Rn, (load addr:$src))]>;
+                          []>;
+}
 
 // STORE TO FRAME
+let mayStore = 1, Defs = [R0, R1], Uses = [R0, R1] in {
+
 def MOVBSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                            "! MOVBSFR $src, $dst",
                            [(truncstorei8 i32:$src, addr:$dst)]>;
@@ -1429,6 +1433,7 @@ def MOVWSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
 def MOVLSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                            "! MOVLSFR $src, $dst",
                            [(store i32:$src, addr:$dst)]>;
+}
 
 //===--------------------------------------------------------------------------===//
 // Stack Frame
@@ -1470,7 +1475,10 @@ def ADJCALLSTACKUP : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
 // Zero-Extend Load
 //===--------------------------------------------------------------------------===//
 
-def : Pat<(i32 (sextloadi1  addr:$src)), (MOVBLFR addr:$src)>;
+def : Pat<(i32 (sextloadi1  addr:$src)), (EXTSB (EXTUB (MOVBLFR addr:$src)))>;
+def : Pat<(i32 (sextloadi8  addr:$src)), (EXTSB (EXTUB (MOVBLFR addr:$src)))>;
+def : Pat<(i32 (sextloadi16 addr:$src)), (EXTSW (MOVWLFR addr:$src))>;
+def : Pat<(i32 (load        addr:$src)),        (MOVLLFR addr:$src)>;
 def : Pat<(i32 (zextloadi1  addr:$src)), (EXTUB (MOVBLFR addr:$src))>;
 def : Pat<(i32 (zextloadi8  addr:$src)), (EXTUB (MOVBLFR addr:$src))>;
 def : Pat<(i32 (zextloadi16 addr:$src)), (EXTUW (MOVWLFR addr:$src))>;

>From f400b654e3f042966a63cb062ff07e32193b8502 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 8 Sep 2026 10:55:19 +0200
Subject: [PATCH 42/67] Add lowering for left and right shifts

---
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 187 ++++++++++++++++++
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  63 +++++-
 2 files changed, 240 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index c09b79239dda4..4f265e3025c99 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -77,6 +77,7 @@ static int64_t getOffsetForStackOffset(const MachineFrameInfo &MFI, int64_t Stac
 
 
 
+
 //===----------------------------------------------------------------------===//
 //                              Frame Stores
 //===----------------------------------------------------------------------===//
@@ -311,6 +312,186 @@ bool SuperHExpandPseudo::expand<SH::MOVLLFR>(Block &MBB, BlockIt MBBI) {
 
 
 
+
+//===----------------------------------------------------------------------===//
+//                              Bit Shifting
+//===----------------------------------------------------------------------===//
+
+template <>
+bool SuperHExpandPseudo::expand<SH::SHLri>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  auto DstReg = MI.getOperand(0).getReg();
+  auto SrcReg = MI.getOperand(1).getReg();
+  int64_t Offset = MI.getOperand(2).getImm();
+
+  while(Offset > 0) {
+
+    if (Offset > 16) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL16), DstReg)
+        .addReg(SrcReg);
+
+      Offset -= 16;
+      continue;
+    }
+
+    if (Offset > 8) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL8), DstReg)
+        .addReg(SrcReg);
+
+      Offset -= 8;
+      continue;
+    }
+
+    if (Offset > 2) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL2), DstReg)
+        .addReg(SrcReg);
+
+      Offset -= 2;
+      continue;
+    }
+
+    BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL), DstReg)
+      .addReg(SrcReg);
+    Offset -= 1;
+    continue;
+  }
+
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::SHRri>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  auto DstReg = MI.getOperand(0).getReg();
+  auto SrcReg = MI.getOperand(1).getReg();
+  int64_t Offset = MI.getOperand(2).getImm();
+
+  while(Offset > 0) {
+    
+    if (Offset > 16) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR16), DstReg)
+        .addReg(SrcReg);
+
+      Offset -= 16;
+      continue;
+    }
+
+    if (Offset > 8) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR8), DstReg)
+        .addReg(SrcReg);
+
+      Offset -= 8;
+      continue;
+    }
+
+    if (Offset > 2) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR2), DstReg)
+        .addReg(SrcReg);
+
+      Offset -= 2;
+      continue;
+    }
+
+    BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR), DstReg)
+      .addReg(SrcReg);
+    Offset -= 1;
+    continue;
+  }
+
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::SRAri>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  auto DstReg = MI.getOperand(0).getReg();
+  auto SrcReg = MI.getOperand(1).getReg();
+  int64_t Offset = MI.getOperand(2).getImm();
+
+  while(Offset > 0) {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::SHAR), DstReg)
+      .addReg(SrcReg);
+    Offset -= 1;
+  }
+
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::SHLrr>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+
+  auto Src1Reg = MI.getOperand(1).getReg();
+  auto Src2Reg = MI.getOperand(2).getReg();
+
+  BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL))
+    .addReg(Src1Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::DT))
+    .addReg(Src2Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
+    .addImm(-4);
+
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::SHRrr>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+
+  auto Src1Reg = MI.getOperand(1).getReg();
+  auto Src2Reg = MI.getOperand(2).getReg();
+
+  BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR))
+    .addReg(Src1Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::DT))
+    .addReg(Src2Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
+    .addImm(-4);
+
+  MI.eraseFromParent();
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::SRArr>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+
+  auto Src1Reg = MI.getOperand(1).getReg();
+  auto Src2Reg = MI.getOperand(2).getReg();
+
+  BuildMI(MBB, MBBI, DL, TII->get(SH::SHAR))
+    .addReg(Src1Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::DT))
+    .addReg(Src2Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
+    .addImm(-4);
+
+  MI.eraseFromParent();
+  return true;
+}
+
+
+
+
 //===----------------------------------------------------------------------===//
 //                            General Interface
 //===----------------------------------------------------------------------===//
@@ -375,6 +556,12 @@ bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
     EXPAND(SH::MOVBLFR);
     EXPAND(SH::MOVWLFR);
     EXPAND(SH::MOVLLFR);
+    EXPAND(SH::SHLri);
+    EXPAND(SH::SHRri);
+    EXPAND(SH::SRAri);
+    EXPAND(SH::SHLrr);
+    EXPAND(SH::SHRrr);
+    EXPAND(SH::SRArr);
   }
 #undef EXPAND
   return false;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 87494648e3102..92e35120815b3 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -1005,58 +1005,58 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
   def SHAR            : InstRn<0b0100000000100001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shar $Rn",
-                              [(set i32:$Rn, (sra i32:$src, (i8 1)))]>;
+                              []>;
 
   // shll Rn
   let Defs = [SR] in
   def SHLL            : InstRn<0b0100000000000000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll $Rn",
-                              [(set i32:$Rn, (shl i32:$src, (i8 1)))]>;
+                              []>;
 
   // shll2 Rn
   let Defs = [SR] in
   def SHLL2           : InstRn<0b0100000000001000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll2 $Rn",
-                              [(set i32:$Rn, (shl i32:$src, (i8 2)))]>;
+                              []>;
 
   // shll8 Rn
   def SHLL8           : InstRn<0b0100000000011000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll8 $Rn",
-                              [(set i32:$Rn, (shl i32:$src, (i8 8)))]>;
+                              []>;
 
   // shll16 Rn
   def SHLL16          : InstRn<0b0100000000101000, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shll16 $Rn",
-                              [(set i32:$Rn, (shl i32:$src, (i8 16)))]>;
+                              []>;
 
   // shlr Rn
   let Defs = [SR] in
   def SHLR            : InstRn<0b0100000000000001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr $Rn",
-                              [(set i32:$Rn, (srl i32:$src, (i8 1)))]>;
+                              []>;
 
   // shlr2 Rn
   def SHLR2           : InstRn<0b0100000000001001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr2 $Rn",
-                              [(set i32:$Rn, (srl i32:$src, (i8 2)))]>;
+                              []>;
 
   // shlr8 Rn
   def SHLR8           : InstRn<0b0100000000011001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr8 $Rn",
-                              [(set i32:$Rn, (srl i32:$src, (i8 8)))]>;
+                              []>;
 
   // shlr16 Rn
   def SHLR16          : InstRn<0b0100000000101001, 
                               (outs GPR:$Rn), (ins GPR:$src),
                               "shlr16 $Rn",
-                              [(set i32:$Rn, (srl i32:$src, (i8 16)))]>;
+                              []>;
 
 }
 
@@ -1421,7 +1421,6 @@ def MOVLLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
 
 // STORE TO FRAME
 let mayStore = 1, Defs = [R0, R1], Uses = [R0, R1] in {
-
 def MOVBSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                            "! MOVBSFR $src, $dst",
                            [(truncstorei8 i32:$src, addr:$dst)]>;
@@ -1435,6 +1434,40 @@ def MOVLSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                            [(store i32:$src, addr:$dst)]>;
 }
 
+//===--------------------------------------------------------------------------===//
+// Shifts
+//===--------------------------------------------------------------------------===//
+
+// Shift by immediate
+let Defs = [SR], Constraints = "$src = $dst" in {
+def SHLri       : SHPseudo<(outs GPR:$dst), (ins GPR:$src, i32imm:$shift),
+                          "! SHL $src, $shift",
+                          []>;
+
+def SHRri       : SHPseudo<(outs GPR:$dst), (ins GPR:$src, i32imm:$shift),
+                          "! SHR $src, $shift",
+                          []>;
+
+def SRAri       : SHPseudo<(outs GPR:$dst), (ins GPR:$src, i32imm:$shift),
+                          "! SRA $src, $shift",
+                          []>;
+}
+
+// Shift by register
+let Defs = [SR], Constraints = "$src1 = $dst" in {
+def SHLrr       : SHPseudo<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2),
+                          "! SHL $src1, $src2",
+                          []>;
+
+def SHRrr       : SHPseudo<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2),
+                          "! SHR $src1, $src2",
+                          []>;
+
+def SRArr       : SHPseudo<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2),
+                          "! SRA $src1, $src2",
+                          []>;
+}
+
 //===--------------------------------------------------------------------------===//
 // Stack Frame
 //===--------------------------------------------------------------------------===//
@@ -1471,6 +1504,16 @@ def ADJCALLSTACKUP : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
+//===--------------------------------------------------------------------------===//
+// Shifts
+//===--------------------------------------------------------------------------===//
+def : Pat<(i32 (shl i32:$src, (i32 timm:$shift))),  (SHLri GPR:$src,  i32imm:$shift)>;
+def : Pat<(i32 (srl i32:$src, (i32 timm:$shift))),  (SHRri GPR:$src,  i32imm:$shift)>;
+def : Pat<(i32 (sra i32:$src, (i32 timm:$shift))),  (SRAri GPR:$src,  i32imm:$shift)>;
+def : Pat<(i32 (shl i32:$src1, i32:$src2)),         (SHLrr GPR:$src1, GPR:$src2)>;
+def : Pat<(i32 (srl i32:$src1, i32:$src2)),         (SHRrr GPR:$src1, GPR:$src2)>;
+def : Pat<(i32 (sra i32:$src1, i32:$src2)),         (SRArr GPR:$src1, GPR:$src2)>;
+
 //===--------------------------------------------------------------------------===//
 // Zero-Extend Load
 //===--------------------------------------------------------------------------===//

>From 30edf938b1ef1d9c20940943fd3045af983c51f0 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 8 Sep 2026 13:17:15 +0200
Subject: [PATCH 43/67] Add global load/store

---
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |  12 +-
 .../SuperH/MCTargetDesc/SuperHInstPrinter.h   |   8 +-
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 371 +++++++++++-------
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  24 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  12 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  77 ++--
 .../SuperH/SuperHMachineFunctionInfo.cpp      |  18 +
 .../Target/SuperH/SuperHMachineFunctionInfo.h |   3 +
 8 files changed, 325 insertions(+), 200 deletions(-)

diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 1ecc1b8fbc0d9..7f3735f501e3b 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -100,11 +100,21 @@ void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream
 
   const MCOperand &Op0 = MI->getOperand(OpNo);
   const MCOperand &Op1 = MI->getOperand(OpNo+1);
+  
+  // For globals, we want to render a symbol.
+  // even if they get lowered beforehand.
+  if (Op0.isExpr()) {
+    if (const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op0.getExpr())) {
+      OS << SymOp->getSymbol().getName();
+      return;
+    }
+    return;
+  }
 
   OS << "@(" << Op1.getImm() << "," << getRegName(Op0.getReg()) << ")";
 }
 
-void SuperHInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
+void SuperHInstPrinter::printMemrii(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
   printOperand(MI, OpNo, O);
 }
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
index 230b3e8cc83e6..2a95c92f064c6 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -49,16 +49,16 @@ class SuperHInstPrinter : public MCInstPrinter {
 private:
   static const char *getRegisterName(MCRegister Reg);
   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
-  void printCPInstOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
 
   template<int Scale>
   void printPCRel(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
-  
-  template<int Scale>
-  void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O);
 
   template<int Scale>
   void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  
+  template<int Scale>
+  void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+  void printMemrii(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index 4f265e3025c99..0b99feed54d88 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -14,6 +14,7 @@
 
 #include "SuperH.h"
 #include "SuperHInstrInfo.h"
+#include "SuperHMachineFunctionInfo.h"
 #include "SuperHTargetMachine.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
 
@@ -21,6 +22,7 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/Support/ErrorHandling.h"
 
 using namespace llvm;
 
@@ -54,6 +56,11 @@ class SuperHExpandPseudo : public MachineFunctionPass {
   bool expandMBB(Block &MBB);
   bool expandMI(Block &MBB, BlockIt MBBI);
   template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
+
+  void storeToFrame(Block &MBB, BlockIt MBBI, int Scale);
+  bool storeToGlobal(Block &MBB, BlockIt MBBI);
+  void loadFromFrame(Block &MBB, BlockIt MBBI, int Scale);
+  bool loadFromGlobal(Block &MBB, BlockIt MBBI);
 };
 
 
@@ -82,8 +89,7 @@ static int64_t getOffsetForStackOffset(const MachineFrameInfo &MFI, int64_t Stac
 //                              Frame Stores
 //===----------------------------------------------------------------------===//
 
-template <>
-bool SuperHExpandPseudo::expand<SH::MOVBSFR>(Block &MBB, BlockIt MBBI) {
+void SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
@@ -93,101 +99,141 @@ bool SuperHExpandPseudo::expand<SH::MOVBSFR>(Block &MBB, BlockIt MBBI) {
   bool SrcIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 1);
-
-  LLVM_DEBUG(dbgs() << "Expanding MOVBSFR to MOVBS4 @"
-                    << " spoffset=" << SpOffset 
-                    << " offset=" << SpOffset-Offset 
-                    <<  "...\n");
+  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, Scale);
 
   // Expand sequence to
-  // mov      <base reg>,r1
-  // add      #-ROff,r1
-  // mov      <src reg>, r0
-  // mov.b    r0,@(ROff+Offset,r1)
+  // mov      <frame reg>,  r1
+  // add      #-SpOffset,   r1
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
     .addReg(FrameReg);
   BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
     .addReg(SH::R1)
     .addImm(-SpOffset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
-    .addReg(SrcReg, getKillRegState(SrcIsKill));
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS4))
-    .addReg(SH::R1, RegState::Kill)
-    .addImm(SpOffset-Offset);
+
+  switch(MI.getOpcode()) {
+  default: llvm_unreachable("Expected valid MOV*SPtr opcode.");
+  case SH::MOVBSPtr: {
+
+    // mov      <src reg>,  r0
+    // mov.b    r0, @(offset,r1)
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
+      .addReg(SrcReg, getKillRegState(SrcIsKill));
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS4))
+      .addReg(SH::R1, RegState::Kill)
+      .addImm(SpOffset-Offset);
+    break;
+  }
+  case SH::MOVWSPtr: {
+
+    // mov      <src reg>,  r0
+    // mov.w    r0, @(offset,r1)
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
+      .addReg(SrcReg, getKillRegState(SrcIsKill));
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS4))
+      .addReg(SH::R1, RegState::Kill)
+      .addImm(SpOffset-Offset);
+    break;
+  }
+  case SH::MOVLSPtr: {
+
+    // mov.b    <src reg>, @(offset,r1)
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
+      .addReg(SrcReg, getKillRegState(SrcIsKill))
+      .addReg(SH::R1, RegState::Kill)
+      .addImm(SpOffset-Offset);
+    break;
+  }
+  }
+  MI.eraseFromParent();
+  return;
+}
+
+bool SuperHExpandPseudo::storeToGlobal(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const SuperHMachineFunctionInfo *FI = MF.getInfo<SuperHMachineFunctionInfo>();
+
+  auto SrcReg = MI.getOperand(0).getReg();
+  auto *G = FI->tryGetConstant(MI.getOperand(1).getGlobal(), MF);
+  if (!G)
+    return false;
+
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
+    .addConstantPoolIndex(G->getLabelId());
+
+  switch(MI.getOpcode()) {
+  default: llvm_unreachable("Expected valid MOV*SPtr opcode.");
+  case SH::MOVBSPtr: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS))
+      .addReg(SrcReg)
+      .addReg(SH::R1);
+    break;
+  }
+  case SH::MOVWSPtr: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS))
+      .addReg(SrcReg)
+      .addReg(SH::R1);
+    break;
+  }
+  case SH::MOVLSPtr: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS))
+      .addReg(SrcReg)
+      .addReg(SH::R1);
+    break;
+  }
+  }
+  
   MI.eraseFromParent();
   return true;
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVWSFR>(Block &MBB, BlockIt MBBI) {
+bool SuperHExpandPseudo::expand<SH::MOVBSPtr>(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
-  auto SrcReg = MI.getOperand(0).getReg();
-  bool SrcIsKill = MI.getOperand(0).isKill();
-  auto FrameReg = MI.getOperand(1).getReg();
-  auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 2);
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVWSFR to MOVWS4 @"
-                    << " spoffset=" << SpOffset 
-                    << " offset=" << SpOffset-Offset 
-                    <<  "...\n");
+  // Store to global.
+  if (MI.getOperand(1).isGlobal()) {
+    return storeToGlobal(MBB, MBBI);
+  }
 
-  // Expand sequence to
-  // mov      <base reg>,r1
-  // add      #-ROff,r1
-  // mov      <src reg>, r0
-  // mov.w    r0,@(ROff+Offset,r1)
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
-    .addReg(FrameReg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-    .addReg(SH::R1)
-    .addImm(-SpOffset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
-    .addReg(SrcReg, getKillRegState(SrcIsKill));
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS4))
-    .addReg(SH::R1, RegState::Kill)
-    .addImm(SpOffset-Offset);
-  MI.eraseFromParent();
+  storeToFrame(MBB, MBBI, 1);
   return true;
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVLSFR>(Block &MBB, BlockIt MBBI) {
+bool SuperHExpandPseudo::expand<SH::MOVWSPtr>(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
-  auto SrcReg = MI.getOperand(0).getReg();
-  bool SrcIsKill = MI.getOperand(0).isKill();
-  auto FrameReg = MI.getOperand(1).getReg();
-  auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 4);
+  // Store to global.
+  if (MI.getOperand(1).isGlobal()) {
+    return storeToGlobal(MBB, MBBI);
+  }
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVLSFR to MOVLS4 @"
-                    << " spoffset=" << SpOffset 
-                    << " offset=" << SpOffset-Offset 
-                    <<  "...\n");
-    
-  // Expand sequence to
-  // mov      <base reg>,r1
-  // add      #-ROff,r1
-  // mov.l    <src reg>,@(ROff+Offset,r1)
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
-    .addReg(FrameReg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-    .addReg(SH::R1)
-    .addImm(-SpOffset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
-    .addReg(SrcReg, getKillRegState(SrcIsKill))
-    .addReg(SH::R1, RegState::Kill)
-    .addImm(SpOffset-Offset);
-  MI.eraseFromParent();
+  storeToFrame(MBB, MBBI, 2);
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVLSPtr>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  // Store to global.
+  if (MI.getOperand(1).isGlobal()) {
+    return storeToGlobal(MBB, MBBI);
+  }
+
+  storeToFrame(MBB, MBBI, 4);
   return true;
 }
 
@@ -198,8 +244,7 @@ bool SuperHExpandPseudo::expand<SH::MOVLSFR>(Block &MBB, BlockIt MBBI) {
 //                               Frame Loads
 //===----------------------------------------------------------------------===//
 
-template <>
-bool SuperHExpandPseudo::expand<SH::MOVBLFR>(Block &MBB, BlockIt MBBI) {
+void SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
@@ -209,104 +254,138 @@ bool SuperHExpandPseudo::expand<SH::MOVBLFR>(Block &MBB, BlockIt MBBI) {
   bool DstIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 1);
+  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, Scale);
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVBLFR to MOVBL4 @"
-                    << " spoffset=" << SpOffset 
-                    << " offset=" << SpOffset-Offset 
-                    <<  "...\n");
-    
   // Expand sequence to
-  // mov      <base reg>,r1
-  // add      #-ROff,r1
-  // mov.b    @(ROff+Offset,r1),r0
-  // mov      r0, <dst reg>
+  // mov      <frame reg>,  r1
+  // add      #-SpOffset,   r1
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
     .addReg(FrameReg);
   BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
     .addReg(SH::R1)
     .addImm(-SpOffset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL4))
-    .addReg(SH::R1)
-    .addImm(SpOffset-Offset)
-    .addReg(SH::R0, RegState::Define);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
-    .addReg(DstReg, getKillRegState(DstIsKill))
-    .addReg(SH::R0, RegState::Kill);
+
+  switch(MI.getOpcode()) {
+  default: llvm_unreachable("Expected valid MOV*LPtr opcode.");
+  case SH::MOVBLPtr: {
+
+    // mov.w    @(offset,r1), r0
+    // mov      r0,           <dst reg>
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL4))
+      .addReg(SH::R1)
+      .addImm(SpOffset-Offset)
+      .addReg(SH::R0, RegState::Define);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
+      .addReg(DstReg, getKillRegState(DstIsKill))
+      .addReg(SH::R0, RegState::Kill);
+    break;
+  }
+  case SH::MOVWLPtr: {
+
+    // mov.b    @(offset,r1), r0
+    // mov      r0,           <dst reg>
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4))
+      .addReg(SH::R1)
+      .addImm(SpOffset-Offset);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
+      .addReg(DstReg, getKillRegState(DstIsKill))
+      .addReg(SH::R0, RegState::Define);
+    break;
+  }
+  case SH::MOVLLPtr: {
+
+    // mov.l    @(offset,r1), <dst reg>
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4))
+      .addReg(DstReg, getKillRegState(DstIsKill))
+      .addReg(SH::R1)
+      .addImm(SpOffset-Offset);
+    break;
+  }
+  }
+  MI.eraseFromParent();
+  return;
+}
+
+bool SuperHExpandPseudo::loadFromGlobal(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const SuperHMachineFunctionInfo *FI = MF.getInfo<SuperHMachineFunctionInfo>();
+
+  auto DstReg = MI.getOperand(0).getReg();
+  auto *G = FI->tryGetConstant(MI.getOperand(1).getGlobal(), MF);
+
+  if (!G)
+    return false;
+
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
+    .addConstantPoolIndex(G->getLabelId());
+
+  switch(MI.getOpcode()) {
+  default: llvm_unreachable("Expected valid MOV*LPtr opcode.");
+  case SH::MOVBLPtr: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL), DstReg)
+      .addReg(SH::R1);
+    break;
+  }
+  case SH::MOVWLPtr: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL), DstReg)
+      .addReg(SH::R1);
+    break;
+  }
+  case SH::MOVLLPtr: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL), DstReg)
+      .addReg(SH::R1);
+    break;
+  }
+  }
+  
   MI.eraseFromParent();
   return true;
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVWLFR>(Block &MBB, BlockIt MBBI) {
+bool SuperHExpandPseudo::expand<SH::MOVBLPtr>(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
-  auto DstReg = MI.getOperand(0).getReg();
-  bool DstIsKill = MI.getOperand(0).isKill();
-  auto FrameReg = MI.getOperand(1).getReg();
-  auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 2);
+  // Load from global.
+  if (MI.getOperand(1).isGlobal())
+    return loadFromGlobal(MBB, MBBI);
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVWLFR to MOVWL4 @"
-                    << " spoffset=" << SpOffset 
-                    << " offset=" << SpOffset-Offset 
-                    <<  "...\n");
-    
-  // Expand sequence to
-  // mov      <base reg>,r1
-  // add      #-ROff,r1
-  // mov.w    @(ROff+Offset,r1),r0
-  // mov      r0, <dst reg>
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
-    .addReg(FrameReg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-    .addReg(SH::R1)
-    .addImm(-SpOffset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4))
-    .addReg(SH::R1)
-    .addImm(SpOffset-Offset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
-    .addReg(DstReg, getKillRegState(DstIsKill))
-    .addReg(SH::R0, RegState::Define);
-  MI.eraseFromParent();
+  loadFromFrame(MBB, MBBI, 1);
   return true;
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVLLFR>(Block &MBB, BlockIt MBBI) {
+bool SuperHExpandPseudo::expand<SH::MOVWLPtr>(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
-  auto DstReg = MI.getOperand(0).getReg();
-  bool DstIsKill = MI.getOperand(0).isKill();
-  auto FrameReg = MI.getOperand(1).getReg();
-  auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, 4);
+  // Load from global.
+  if (MI.getOperand(1).isGlobal())
+    return loadFromGlobal(MBB, MBBI);
 
-  LLVM_DEBUG(dbgs() << "Expanding MOVLLFR to MOVLL4 @"
-                    << " spoffset=" << SpOffset 
-                    << " offset=" << SpOffset-Offset 
-                    <<  "...\n");
-    
-  // Expand sequence to
-  // mov      <base reg>,r1
-  // add      #-ROff,r1
-  // mov.l    @(ROff+Offset,r1),<dest reg>
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
-    .addReg(FrameReg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-    .addReg(SH::R1)
-    .addImm(-SpOffset);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4))
-    .addReg(DstReg, getKillRegState(DstIsKill))
-    .addReg(SH::R1)
-    .addImm(SpOffset-Offset);
-  MI.eraseFromParent();
+  loadFromFrame(MBB, MBBI, 2);
+  return true;
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVLLPtr>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  // Load from global.
+  if (MI.getOperand(1).isGlobal())
+    return loadFromGlobal(MBB, MBBI);
+
+  loadFromFrame(MBB, MBBI, 4);
   return true;
 }
 
@@ -550,12 +629,12 @@ bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
     return expand<Op>(MBB, MI)
 
   switch(Opcode) {
-    EXPAND(SH::MOVBSFR);
-    EXPAND(SH::MOVWSFR);
-    EXPAND(SH::MOVLSFR);
-    EXPAND(SH::MOVBLFR);
-    EXPAND(SH::MOVWLFR);
-    EXPAND(SH::MOVLLFR);
+    EXPAND(SH::MOVBSPtr);
+    EXPAND(SH::MOVWSPtr);
+    EXPAND(SH::MOVLSPtr);
+    EXPAND(SH::MOVBLPtr);
+    EXPAND(SH::MOVWLPtr);
+    EXPAND(SH::MOVLLPtr);
     EXPAND(SH::SHLri);
     EXPAND(SH::SHRri);
     EXPAND(SH::SRAri);
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index e6822a465acca..aa2e1f3ba0d8a 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -142,6 +142,8 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
   SDLoc dl(Op);
   auto DL = CurDAG->getDataLayout();
   MVT PtrVT = getTargetLowering()->getPointerTy(DL);
+  MachineFunction &MF = CurDAG->getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
 
   // if the address is a frame index get the TargetFrameIndex.
   if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
@@ -150,6 +152,12 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
     return true;
   }
 
+  // if the address is a wrapper, get the underlying data.
+  if (N.getOpcode() == SHISD::WRAPPER) {
+    Base = N->getOperand(0);
+    Disp = N;
+    return true;
+  }
   return false;
 }
 
@@ -168,9 +176,9 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
   SDValue N0 = N->getOperand(0);
 
-  // Global Addresses
-  if (GlobalAddressSDNode* GA = dyn_cast<GlobalAddressSDNode>(N0.getNode())) {
-    if (auto *CPV = SFI->tryGetConstant(GA, *CurDAG, SHCP::no_modifier)) {
+  // External Symbols
+  if (ExternalSymbolSDNode* Sym = dyn_cast<ExternalSymbolSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(Sym, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
       ReplaceNode(N, Res);
@@ -188,9 +196,8 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
     }
   }
 
-  // External Symbols
-  if (ExternalSymbolSDNode* Sym = dyn_cast<ExternalSymbolSDNode>(N0.getNode())) {
-    if (auto *CPV = SFI->tryGetConstant(Sym, *CurDAG, SHCP::no_modifier)) {
+  if (ConstantSDNode* Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
       ReplaceNode(N, Res);
@@ -198,8 +205,9 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
     }
   }
 
-  if (ConstantSDNode* Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
-    if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
+  // Global Addresses
+  if (GlobalAddressSDNode* GA = dyn_cast<GlobalAddressSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(GA, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
       ReplaceNode(N, Res);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 7f8095d0a3a73..8eae955dfffc7 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -202,17 +202,17 @@ void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBl
                     << " size=" << ObjectSize << "\n");
 
   if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVBSFR))
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVBSPtr))
       .addReg(SrcReg, getKillRegState(isKill))
       .addFrameIndex(FrameIndex)
       .addImm(0);
   } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVWSFR))
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVWSPtr))
       .addReg(SrcReg, getKillRegState(isKill))
       .addFrameIndex(FrameIndex)
       .addImm(0);
   } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVLSFR))
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVLSPtr))
       .addReg(SrcReg, getKillRegState(isKill))
       .addFrameIndex(FrameIndex)
       .addImm(0);
@@ -241,17 +241,17 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
                     << " size=" << ObjectSize << "\n");
 
   if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVBLFR), DestReg)
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVBLPtr), DestReg)
       .addFrameIndex(FrameIndex)
       .addImm(0);
 
   } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVWLFR), DestReg)
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVWLPtr), DestReg)
       .addFrameIndex(FrameIndex)
       .addImm(0);
 
   } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVLLFR), DestReg)
+    BuildMI(MBB, II, DebugLoc(), get(SH::MOVLLPtr), DestReg)
       .addFrameIndex(FrameIndex)
       .addImm(0);
   } else {
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 92e35120815b3..1af8a591b5458 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -214,8 +214,10 @@ def brtarget       : Operand<OtherVT> {
 }
 
 // An operand for the CONSTPOOL_ENTRY pseudo-instruction.
-def cpinst_operand : Operand<i32> {
-  let PrintMethod = "printCPInstOperand";
+// Double-indirect memory operand.
+def memrii : Operand<i32> {
+  let OperandType = "OPERAND_MEMORY";
+  let PrintMethod = "printMemrii";
 }
 
 // Register Indirect
@@ -1404,36 +1406,40 @@ def Select32    : SHSelectPseudo<(outs GPR:$dst),
 // Frame Load/Store
 //===--------------------------------------------------------------------------===//
 
-// LOAD FROM FRAME
+// LOAD FROM ADDRESS
 let mayLoad = 1, Defs = [R0, R1], Uses = [R0, R1] in {
-def MOVBLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
-                          "! MOVBLFR $src, $Rn",
-                          []>;
+def MOVBLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVBLPtr $src, $Rn",
+                            []>;
 
-def MOVWLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
-                          "! MOVWLFR $src, $Rn",
-                          []>;
+def MOVWLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVWLPtr $src, $Rn",
+                            []>;
 
-def MOVLLFR : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
-                          "! MOVLLFR $src, $Rn",
-                          []>;
+def MOVLLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVLLPtr $src, $Rn",
+                            []>;
 }
 
-// STORE TO FRAME
+// STORE TO ADDRESS
 let mayStore = 1, Defs = [R0, R1], Uses = [R0, R1] in {
-def MOVBSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
-                           "! MOVBSFR $src, $dst",
-                           [(truncstorei8 i32:$src, addr:$dst)]>;
+def MOVBSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVBSPtr $src, $dst",
+                             [(truncstorei8 i32:$src, addr:$dst)]>;
 
-def MOVWSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
-                           "! MOVWSFR $src, $dst",
-                           [(truncstorei16 i32:$src, addr:$dst)]>;
+def MOVWSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVWSPtr $src, $dst",
+                             [(truncstorei16 i32:$src, addr:$dst)]>;
 
-def MOVLSFR : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
-                           "! MOVLSFR $src, $dst",
-                           [(store i32:$src, addr:$dst)]>;
+def MOVLSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVLSPtr $src, $dst",
+                             [(store i32:$src, addr:$dst)]>;
 }
 
+
+
+
+
 //===--------------------------------------------------------------------------===//
 // Shifts
 //===--------------------------------------------------------------------------===//
@@ -1482,7 +1488,7 @@ def SHFrmIdx : SHPseudo<(outs GPR:$dst), (ins GPR:$src, disp12:$src2)>;
 /// is the index into the MachineConstantPool that this is, the third is the
 /// size in bytes of this constant pool entry.
 let hasSideEffects = 0, isNotDuplicable = 1, hasNoSchedulingInfo = 1 in
-def CONSTPOOL_ENTRY : SHPseudo<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size), 
+def CONSTPOOL_ENTRY : SHPseudo<(outs), (ins memrii:$instid, memrii:$cpidx, i32imm:$size), 
                               "!CONSTPOOL_ENTRY $instid, $cpidx, $size",
                               []>;
 
@@ -1504,6 +1510,10 @@ def ADJCALLSTACKUP : SHPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
+def : Pat<(sext_inreg i32:$src, i1),  (EXTSB i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i8),  (EXTSB i32:$src)>;
+def : Pat<(sext_inreg i32:$src, i16), (EXTSW i32:$src)>;
+
 //===--------------------------------------------------------------------------===//
 // Shifts
 //===--------------------------------------------------------------------------===//
@@ -1515,17 +1525,14 @@ def : Pat<(i32 (srl i32:$src1, i32:$src2)),         (SHRrr GPR:$src1, GPR:$src2)
 def : Pat<(i32 (sra i32:$src1, i32:$src2)),         (SRArr GPR:$src1, GPR:$src2)>;
 
 //===--------------------------------------------------------------------------===//
-// Zero-Extend Load
+// Loads
 //===--------------------------------------------------------------------------===//
 
-def : Pat<(i32 (sextloadi1  addr:$src)), (EXTSB (EXTUB (MOVBLFR addr:$src)))>;
-def : Pat<(i32 (sextloadi8  addr:$src)), (EXTSB (EXTUB (MOVBLFR addr:$src)))>;
-def : Pat<(i32 (sextloadi16 addr:$src)), (EXTSW (MOVWLFR addr:$src))>;
-def : Pat<(i32 (load        addr:$src)),        (MOVLLFR addr:$src)>;
-def : Pat<(i32 (zextloadi1  addr:$src)), (EXTUB (MOVBLFR addr:$src))>;
-def : Pat<(i32 (zextloadi8  addr:$src)), (EXTUB (MOVBLFR addr:$src))>;
-def : Pat<(i32 (zextloadi16 addr:$src)), (EXTUW (MOVWLFR addr:$src))>;
-
-def : Pat<(sext_inreg i32:$src, i1),  (EXTSB i32:$src)>;
-def : Pat<(sext_inreg i32:$src, i8),  (EXTSB i32:$src)>;
-def : Pat<(sext_inreg i32:$src, i16), (EXTSW i32:$src)>;
\ No newline at end of file
+def : Pat<(i32 (load        addr:$src)),               (MOVLLPtr addr:$src)>;
+def : Pat<(i32 (sextloadi1  addr:$src)), (EXTSB (EXTUB (MOVBLPtr addr:$src)))>;
+def : Pat<(i32 (sextloadi8  addr:$src)), (EXTSB (EXTUB (MOVBLPtr addr:$src)))>;
+def : Pat<(i32 (sextloadi16 addr:$src)),        (EXTSW (MOVWLPtr addr:$src))>;
+def : Pat<(i32 (load        addr:$src)),               (MOVLLPtr addr:$src)>;
+def : Pat<(i32 (zextloadi1  addr:$src)),        (EXTUB (MOVBLPtr addr:$src))>;
+def : Pat<(i32 (zextloadi8  addr:$src)),        (EXTUB (MOVBLPtr addr:$src))>;
+def : Pat<(i32 (zextloadi16 addr:$src)),        (EXTUW (MOVWLPtr addr:$src))>;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
index f25c7be39daf3..dd009e48c198f 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -13,6 +13,7 @@
 
 #include "SuperHMachineFunctionInfo.h"
 #include "SuperHConstantPoolValue.h"
+#include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include <type_traits>
 
@@ -60,6 +61,23 @@ SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
   );
 }
 
+SuperHConstantPoolConstant *
+SuperHMachineFunctionInfo::tryGetConstant(const GlobalValue *G, const MachineFunction& MF) const {
+
+  // Run though the constant pool that is tied to the DAG and search for 
+  // the constant there.
+  const MachineConstantPool *MCP = MF.getConstantPool();
+  for (auto &MC : MCP->getConstants()) {
+    if (MC.isMachineConstantPoolEntry()) {
+      if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+        if (CPV->getGV() == G)
+          return CPV;
+      }
+    }
+  }
+  return nullptr;
+}
+
 SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
         BlockAddressSDNode *N, 
         SelectionDAG &DAG, 
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
index db3fade2466ae..a162f3dc36244 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -62,6 +62,9 @@ class SuperHMachineFunctionInfo : public MachineFunctionInfo {
   SuperHConstantPoolConstant *tryGetConstant(ConstantSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
   SuperHConstantPoolSymbol *tryGetConstant(ExternalSymbolSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
 
+  // Helper for lower level passes that gets global value constants.
+  SuperHConstantPoolConstant *tryGetConstant(const GlobalValue *G, const MachineFunction& MF) const;
+
 private:
 	virtual void anchor();
 };

>From 5e2d653381987665847a4c3b0bc068a8c1a41561 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 9 Sep 2026 09:22:22 +0200
Subject: [PATCH 44/67] Fix stack slot i8 and i16 loads and stores

---
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 37 +++++++++++++---------
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 8eae955dfffc7..2dad985974518 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -201,23 +201,29 @@ void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBl
                     << " to slot " << FrameIndex
                     << " size=" << ObjectSize << "\n");
 
-  if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
+  switch(ObjectSize) {
+  default: llvm_unreachable("Cannot store this register into stack slot!");
+  case 1: {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVBSPtr))
       .addReg(SrcReg, getKillRegState(isKill))
       .addFrameIndex(FrameIndex)
       .addImm(0);
-  } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
+    break;
+  }
+  case 2: {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVWSPtr))
       .addReg(SrcReg, getKillRegState(isKill))
       .addFrameIndex(FrameIndex)
       .addImm(0);
-  } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
+    break;
+  }
+  case 4: {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVLSPtr))
       .addReg(SrcReg, getKillRegState(isKill))
       .addFrameIndex(FrameIndex)
       .addImm(0);
-  } else {
-    llvm_unreachable("Cannot store this register into stack slot!");
+    break;
+  }
   }
 }
 
@@ -240,28 +246,31 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
                     << " from slot " << FrameIndex
                     << " size=" << ObjectSize << "\n");
 
-  if (RI.isTypeLegalForClass(*RC, MVT::i8)) {
+  switch(ObjectSize) {
+  default: llvm_unreachable("Cannot load this register from stack slot!");
+  case 1: {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVBLPtr), DestReg)
       .addFrameIndex(FrameIndex)
       .addImm(0);
+    break;
+  }
 
-  } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {
+  case 2: {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVWLPtr), DestReg)
       .addFrameIndex(FrameIndex)
       .addImm(0);
-
-  } else if (RI.isTypeLegalForClass(*RC, MVT::i32)) {
+    break;
+  }
+  case 4: {
     BuildMI(MBB, II, DebugLoc(), get(SH::MOVLLPtr), DestReg)
       .addFrameIndex(FrameIndex)
       .addImm(0);
-  } else {
-    llvm_unreachable("Cannot load this register from stack slot!");
+    break;
+  }
   }
 }
 
 Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
-  LLVM_DEBUG(dbgs() << "isLoadFromStackSlot\n");
-
   if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
       MI.getOperand(2).getImm() == 0) {
     FrameIndex = MI.getOperand(1).getIndex();
@@ -271,8 +280,6 @@ Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &Frame
 }
 
 Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const {
-  LLVM_DEBUG(dbgs() << "isStoreToStackSlot\n");
-
   if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
       MI.getOperand(1).getImm() == 0) {
     FrameIndex = MI.getOperand(0).getIndex();

>From b9b56accfd82042cc6f0e15813b1fe83d91d8e35 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 9 Sep 2026 09:38:36 +0200
Subject: [PATCH 45/67] Refactor trySelect

---
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 45 ++++++++++---------
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index aa2e1f3ba0d8a..35cdeb387f5ae 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -103,13 +103,9 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
   void Select(SDNode *N) override;
 
   bool trySelect(SDNode *N);
-  bool trySelectSDIV(SDNode *N);
-  bool trySelectUDIV(SDNode *N);
-  bool trySelectFrameIndex(SDNode *N);
-  bool trySelectWrapper(SDNode *N);
-  bool trySelectCMP(SDNode *N);
-  bool trySelectBRCOND(SDNode *N);
-  bool trySelectSELECT_CC(SDNode *N);
+
+  template<unsigned Opcode>
+  bool trySelect(SDNode *N);
 
   const SuperHSubtarget *Subtarget;
 };
@@ -168,7 +164,8 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
 //                             Address Lowering
 //===----------------------------------------------------------------------===//
 
-bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
+template<>
+bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
   auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
   auto DL = SDLoc(N);
 
@@ -224,7 +221,8 @@ bool SuperHDAGToDAGISel::trySelectWrapper(SDNode *N) {
 //                          Conditionals Lowering
 //===----------------------------------------------------------------------===//
 
-bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
+template<>
+bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
   SDValue LHS = N->getOperand(0);
   SDValue RHS = N->getOperand(1);
   ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
@@ -279,7 +277,8 @@ bool SuperHDAGToDAGISel::trySelectCMP(SDNode *N) {
   return false;
 }
 
-bool SuperHDAGToDAGISel::trySelectBRCOND(SDNode *N) {
+template<>
+bool SuperHDAGToDAGISel::trySelect<SHISD::BRCOND>(SDNode *N) {
   SDValue Chain = N->getOperand(0);
   SDValue Dest = N->getOperand(1);
   ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
@@ -325,7 +324,8 @@ bool SuperHDAGToDAGISel::trySelectBRCOND(SDNode *N) {
 //                             Branch Lowering
 //===----------------------------------------------------------------------===//
 
-bool SuperHDAGToDAGISel::trySelectFrameIndex(SDNode *N) {
+template<>
+bool SuperHDAGToDAGISel::trySelect<ISD::FrameIndex>(SDNode *N) {
   auto DL = CurDAG->getDataLayout();
 
   // Get the effective address of the stack slot.
@@ -347,7 +347,12 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
   unsigned Opcode = N->getOpcode();
   SDLoc DL(N);
 
+#define SELECT(Op)                                                             \
+  case Op:                                                                     \
+    return trySelect<Op>(N)
+
   switch(Opcode) {
+  default: break;
   case ISD::GLOBAL_OFFSET_TABLE: {
     SDValue GOT = CurDAG->getTargetExternalSymbol(
         "_GLOBAL_OFFSET_TABLE_", MVT::i32, SHII::MO_GOTPC);
@@ -356,17 +361,15 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
     ReplaceNode(N, Res);
     return true;
   }
-  case ISD::FrameIndex:
-    return trySelectFrameIndex(N);
-  case SHISD::WRAPPER:
-    return trySelectWrapper(N);
-  case SHISD::CMP:
-    return trySelectCMP(N);
-  case SHISD::BRCOND:
-    return trySelectBRCOND(N);
-  default:
-    return false;
+
+  SELECT(ISD::FrameIndex);
+  SELECT(SHISD::WRAPPER);
+  SELECT(SHISD::BRCOND);
+  SELECT(SHISD::CMP);
   }
+
+#undef SELECT
+  return false;
 }
 
 void SuperHDAGToDAGISel::Select(SDNode *N) {

>From caf5cf3671356c9f3535bb7cee5163b8d286a135 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 9 Sep 2026 09:40:54 +0200
Subject: [PATCH 46/67] Fix malformed frame offset in lowering

---
 llvm/lib/Target/SuperH/SuperHFrameLowering.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 8ecd1d9a753f5..b028f9072dc33 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -136,8 +136,7 @@ SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
 
   // NOTE:  All the frame indices are relative to the stack/frame pointer
   //        post-offset. as such an extra adjustment is needed here.
-  int64_t FrameOffset = MFI.getObjectOffset(FI)+1;
-
+  int64_t FrameOffset = MFI.getObjectOffset(FI);
 
   // R14 base
   if (HasFP) {

>From 514f414a8c4eed0d927ce52da125ad24d318ca03 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 14 Sep 2026 09:21:04 +0200
Subject: [PATCH 47/67] Add frame fixup MI pass

---
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |   2 +-
 llvm/lib/Target/SuperH/SuperH.h               |   1 +
 llvm/lib/Target/SuperH/SuperHCallingConv.td   |   8 +-
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 169 +++++++-------
 .../lib/Target/SuperH/SuperHFrameLowering.cpp | 133 +++++++++--
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  98 ++++-----
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 207 ++++++++++++++----
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |   3 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 155 ++++++-------
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |  29 ++-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  66 +++++-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp |   7 +-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.h   |   4 +
 llvm/lib/Target/SuperH/SuperHSubtarget.h      |   1 +
 .../lib/Target/SuperH/SuperHTargetMachine.cpp |   5 +-
 15 files changed, 585 insertions(+), 303 deletions(-)

diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 7f3735f501e3b..22b993ca7208a 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -100,7 +100,7 @@ void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream
 
   const MCOperand &Op0 = MI->getOperand(OpNo);
   const MCOperand &Op1 = MI->getOperand(OpNo+1);
-  
+
   // For globals, we want to render a symbol.
   // even if they get lowered beforehand.
   if (Op0.isExpr()) {
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index 450191c721631..efd8275d96c02 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -29,6 +29,7 @@ FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLe
 FunctionPass *createSuperHFillDelaySlotsPass();
 FunctionPass *createSuperHConstantIslandPass();
 FunctionPass *createSuperHExpandPseudoPass();
+FunctionPass *createSuperHFrameFixupPass();
 
 void initializeSuperHDAGToDAGISelLegacyPass(PassRegistry &);
 void initializeSuperHAsmPrinterPass(PassRegistry &);
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index 20dc3f3ad42d9..937eca18d3001 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -17,10 +17,12 @@ def CC_SH : CallingConv<[
   // All lower size parameters are promoted to 32-bit
   CCIfType<[i1, i8, i16],  CCPromoteToType<i32>>,
   CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
+
+  CCAssignToStack<4, 4>
 ]>;
 
 def RetCC_SH : CallingConv<[
-  CCIfSRet<CCCustom<"RetCC_SuperH_SRet">>,
+  CCIfSRet<CCCustom<"RetCC_SH_SRet">>,
 
   // All lower size parameters are promoted to 32-bit
   CCIfType<[i1, i8, i16],  CCPromoteToType<i32>>,
@@ -32,5 +34,7 @@ def RetCC_SH : CallingConv<[
 // Callee-saved register lists.
 //===----------------------------------------------------------------------===//
 
+def CSR_NoRegs : CalleeSavedRegs<(add)>;
+
 def CSR_SH : CalleeSavedRegs<(add R8, R9, R10, R11, R12, 
-										R13, R14, R15)>;
\ No newline at end of file
+										R13, R14, R15)>;
diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index 0b99feed54d88..2d69d0859cde6 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -15,6 +15,7 @@
 #include "SuperH.h"
 #include "SuperHInstrInfo.h"
 #include "SuperHMachineFunctionInfo.h"
+#include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
 
@@ -33,6 +34,9 @@ using namespace llvm;
 static cl::opt<bool>
 CNoExpand("sh-no-expand", cl::Hidden, cl::init(false),
           cl::desc("Force the backend to not expand instructions."));
+static cl::opt<bool>
+CKeepPseudo("sh-keep-pseudo", cl::Hidden, cl::init(false),
+          cl::desc("Force the backend to keep pseudos around."));
 #endif
 
 namespace {
@@ -57,9 +61,9 @@ class SuperHExpandPseudo : public MachineFunctionPass {
   bool expandMI(Block &MBB, BlockIt MBBI);
   template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
 
-  void storeToFrame(Block &MBB, BlockIt MBBI, int Scale);
+  bool storeToFrame(Block &MBB, BlockIt MBBI, int Scale);
   bool storeToGlobal(Block &MBB, BlockIt MBBI);
-  void loadFromFrame(Block &MBB, BlockIt MBBI, int Scale);
+  bool loadFromFrame(Block &MBB, BlockIt MBBI, int Scale);
   bool loadFromGlobal(Block &MBB, BlockIt MBBI);
 };
 
@@ -72,8 +76,9 @@ class SuperHExpandPseudo : public MachineFunctionPass {
 
 // getOffsetForStackOffset - Calculates how much to offset the stack pointer for
 // the indirect load/store to be in range.
-static int64_t getOffsetForStackOffset(const MachineFrameInfo &MFI, int64_t StackOffset, 
+static int64_t getOffsetForStackOffset(const MachineFunction &MF, 
                                        uint8_t Bits, uint8_t Scale = 1) {
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
   
   // The base value range for the instruction.
   int64_t BM = ((1<<Bits)-1)*Scale;
@@ -82,6 +87,19 @@ static int64_t getOffsetForStackOffset(const MachineFrameInfo &MFI, int64_t Stac
   return alignTo((BM*Slot)+(StackSize%BM), Scale);
 }
 
+// eraseMI - Helper that erases a machine instruction while respecting
+// the debug option to keep them.
+static bool eraseMI(MachineInstr &MI) {
+
+#ifndef NDEBUG
+  if (CKeepPseudo)
+    return false;
+#endif
+  
+  MI.eraseFromParent();
+  return true;
+}
+
 
 
 
@@ -89,17 +107,19 @@ static int64_t getOffsetForStackOffset(const MachineFrameInfo &MFI, int64_t Stac
 //                              Frame Stores
 //===----------------------------------------------------------------------===//
 
-void SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
+bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
   const DebugLoc &DL = MBBI->getDebugLoc();
-  MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  MachineInstr &MI = *MBBI;
+
+  MI.dump();
+  dbgs() << "\n";
 
   auto SrcReg = MI.getOperand(0).getReg();
   bool SrcIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, Scale);
+  int64_t SpOffset = getOffsetForStackOffset(MF, 4, Scale);
 
   // Expand sequence to
   // mov      <frame reg>,  r1
@@ -120,7 +140,7 @@ void SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
       .addReg(SrcReg, getKillRegState(SrcIsKill));
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS4))
       .addReg(SH::R1, RegState::Kill)
-      .addImm(SpOffset-Offset);
+      .addImm(Offset);
     break;
   }
   case SH::MOVWSPtr: {
@@ -131,7 +151,7 @@ void SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
       .addReg(SrcReg, getKillRegState(SrcIsKill));
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS4))
       .addReg(SH::R1, RegState::Kill)
-      .addImm(SpOffset-Offset);
+      .addImm(Offset);
     break;
   }
   case SH::MOVLSPtr: {
@@ -140,12 +160,12 @@ void SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
       .addReg(SrcReg, getKillRegState(SrcIsKill))
       .addReg(SH::R1, RegState::Kill)
-      .addImm(SpOffset-Offset);
+      .addImm(Offset);
     break;
   }
   }
-  MI.eraseFromParent();
-  return;
+
+  return eraseMI(MI);
 }
 
 bool SuperHExpandPseudo::storeToGlobal(Block &MBB, BlockIt MBBI) {
@@ -184,57 +204,43 @@ bool SuperHExpandPseudo::storeToGlobal(Block &MBB, BlockIt MBBI) {
   }
   }
   
-  MI.eraseFromParent();
-  return true;
+  return eraseMI(MI);
 }
 
 template <>
 bool SuperHExpandPseudo::expand<SH::MOVBSPtr>(Block &MBB, BlockIt MBBI) {
-  const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
-
 
   // Store to global.
   if (MI.getOperand(1).isGlobal()) {
     return storeToGlobal(MBB, MBBI);
   }
 
-  storeToFrame(MBB, MBBI, 1);
-  return true;
+  return storeToFrame(MBB, MBBI, 1);
 }
 
 template <>
 bool SuperHExpandPseudo::expand<SH::MOVWSPtr>(Block &MBB, BlockIt MBBI) {
-  const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   // Store to global.
   if (MI.getOperand(1).isGlobal()) {
     return storeToGlobal(MBB, MBBI);
   }
 
-  storeToFrame(MBB, MBBI, 2);
-  return true;
+  return storeToFrame(MBB, MBBI, 2);
 }
 
 template <>
 bool SuperHExpandPseudo::expand<SH::MOVLSPtr>(Block &MBB, BlockIt MBBI) {
-  const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   // Store to global.
   if (MI.getOperand(1).isGlobal()) {
     return storeToGlobal(MBB, MBBI);
   }
 
-  storeToFrame(MBB, MBBI, 4);
-  return true;
+  return storeToFrame(MBB, MBBI, 4);
 }
 
 
@@ -244,17 +250,16 @@ bool SuperHExpandPseudo::expand<SH::MOVLSPtr>(Block &MBB, BlockIt MBBI) {
 //                               Frame Loads
 //===----------------------------------------------------------------------===//
 
-void SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
+bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
   const DebugLoc &DL = MBBI->getDebugLoc();
-  MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  MachineInstr &MI = *MBBI;
 
   auto DstReg = MI.getOperand(0).getReg();
   bool DstIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MFI, Offset, 4, Scale);
+  int64_t SpOffset = getOffsetForStackOffset(MF, 4, Scale);
 
   // Expand sequence to
   // mov      <frame reg>,  r1
@@ -273,7 +278,7 @@ void SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
     // mov      r0,           <dst reg>
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL4))
       .addReg(SH::R1)
-      .addImm(SpOffset-Offset)
+      .addImm(Offset)
       .addReg(SH::R0, RegState::Define);
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
       .addReg(DstReg, getKillRegState(DstIsKill))
@@ -286,7 +291,7 @@ void SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
     // mov      r0,           <dst reg>
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4))
       .addReg(SH::R1)
-      .addImm(SpOffset-Offset);
+      .addImm(Offset);
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
       .addReg(DstReg, getKillRegState(DstIsKill))
       .addReg(SH::R0, RegState::Define);
@@ -298,12 +303,12 @@ void SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4))
       .addReg(DstReg, getKillRegState(DstIsKill))
       .addReg(SH::R1)
-      .addImm(SpOffset-Offset);
+      .addImm(Offset);
     break;
   }
   }
-  MI.eraseFromParent();
-  return;
+  
+  return eraseMI(MI);
 }
 
 bool SuperHExpandPseudo::loadFromGlobal(Block &MBB, BlockIt MBBI) {
@@ -340,53 +345,40 @@ bool SuperHExpandPseudo::loadFromGlobal(Block &MBB, BlockIt MBBI) {
   }
   }
   
-  MI.eraseFromParent();
-  return true;
+  return eraseMI(MI);
 }
 
 template <>
 bool SuperHExpandPseudo::expand<SH::MOVBLPtr>(Block &MBB, BlockIt MBBI) {
-  const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   // Load from global.
   if (MI.getOperand(1).isGlobal())
     return loadFromGlobal(MBB, MBBI);
 
-  loadFromFrame(MBB, MBBI, 1);
-  return true;
+  return loadFromFrame(MBB, MBBI, 1);
 }
 
 template <>
 bool SuperHExpandPseudo::expand<SH::MOVWLPtr>(Block &MBB, BlockIt MBBI) {
-  const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   // Load from global.
   if (MI.getOperand(1).isGlobal())
     return loadFromGlobal(MBB, MBBI);
 
-  loadFromFrame(MBB, MBBI, 2);
-  return true;
+  return loadFromFrame(MBB, MBBI, 2);
 }
 
 template <>
 bool SuperHExpandPseudo::expand<SH::MOVLLPtr>(Block &MBB, BlockIt MBBI) {
-  const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   // Load from global.
   if (MI.getOperand(1).isGlobal())
     return loadFromGlobal(MBB, MBBI);
 
-  loadFromFrame(MBB, MBBI, 4);
-  return true;
+  return loadFromFrame(MBB, MBBI, 4);
 }
 
 
@@ -438,9 +430,8 @@ bool SuperHExpandPseudo::expand<SH::SHLri>(Block &MBB, BlockIt MBBI) {
     Offset -= 1;
     continue;
   }
-
-  MI.eraseFromParent();
-  return true;
+  
+  return eraseMI(MI);
 }
 
 template <>
@@ -485,9 +476,8 @@ bool SuperHExpandPseudo::expand<SH::SHRri>(Block &MBB, BlockIt MBBI) {
     Offset -= 1;
     continue;
   }
-
-  MI.eraseFromParent();
-  return true;
+  
+  return eraseMI(MI);
 }
 
 template <>
@@ -506,9 +496,8 @@ bool SuperHExpandPseudo::expand<SH::SRAri>(Block &MBB, BlockIt MBBI) {
       .addReg(SrcReg);
     Offset -= 1;
   }
-
-  MI.eraseFromParent();
-  return true;
+  
+  return eraseMI(MI);
 }
 
 template <>
@@ -526,8 +515,7 @@ bool SuperHExpandPseudo::expand<SH::SHLrr>(Block &MBB, BlockIt MBBI) {
   BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
     .addImm(-4);
 
-  MI.eraseFromParent();
-  return true;
+  return eraseMI(MI);
 }
 
 template <>
@@ -545,8 +533,7 @@ bool SuperHExpandPseudo::expand<SH::SHRrr>(Block &MBB, BlockIt MBBI) {
   BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
     .addImm(-4);
 
-  MI.eraseFromParent();
-  return true;
+  return eraseMI(MI);
 }
 
 template <>
@@ -564,8 +551,22 @@ bool SuperHExpandPseudo::expand<SH::SRArr>(Block &MBB, BlockIt MBBI) {
   BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
     .addImm(-4);
 
-  MI.eraseFromParent();
-  return true;
+  return eraseMI(MI);
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+//                          Conditional Branching
+//===----------------------------------------------------------------------===//
+
+template <>
+bool SuperHExpandPseudo::expand<SH::BRCC>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+
+  return eraseMI(MI);
 }
 
 
@@ -589,6 +590,7 @@ bool SuperHExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
 }
 
 bool SuperHExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
+  LLVM_DEBUG(dbgs() << "\n********** SuperHExpandPseudo **********\n");
   bool Modified = false;
 
   #ifndef NDEBUG
@@ -629,18 +631,19 @@ bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
     return expand<Op>(MBB, MI)
 
   switch(Opcode) {
-    EXPAND(SH::MOVBSPtr);
-    EXPAND(SH::MOVWSPtr);
-    EXPAND(SH::MOVLSPtr);
-    EXPAND(SH::MOVBLPtr);
-    EXPAND(SH::MOVWLPtr);
-    EXPAND(SH::MOVLLPtr);
-    EXPAND(SH::SHLri);
-    EXPAND(SH::SHRri);
-    EXPAND(SH::SRAri);
-    EXPAND(SH::SHLrr);
-    EXPAND(SH::SHRrr);
-    EXPAND(SH::SRArr);
+  default: break;
+  EXPAND(SH::MOVBSPtr);
+  EXPAND(SH::MOVWSPtr);
+  EXPAND(SH::MOVLSPtr);
+  EXPAND(SH::MOVBLPtr);
+  EXPAND(SH::MOVWLPtr);
+  EXPAND(SH::MOVLLPtr);
+  EXPAND(SH::SHLri);
+  EXPAND(SH::SHRri);
+  EXPAND(SH::SRAri);
+  EXPAND(SH::SHLrr);
+  EXPAND(SH::SHRrr);
+  EXPAND(SH::SRArr);
   }
 #undef EXPAND
   return false;
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index b028f9072dc33..2721e9e614112 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -18,9 +18,11 @@
 #include "SuperHRegisterInfo.h"
 #include "SuperHSubtarget.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
@@ -279,20 +281,14 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
   DebugLoc DL = MBB.findDebugLoc(MI);
   MachineFunction &MF = *MBB.getParent();
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
-  const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
   const TargetInstrInfo &TII = *STI.getInstrInfo();
-  Register SP = RII.getStackRegister();
-
   for (const CalleeSavedInfo &I : reverse(CSI)) {
-    MCRegister Reg = I.getReg();
-    BuildMI(MBB, MI, DL, TII.get(SH::MOVLM), SP)
-      .addReg(Reg)
-      .setMIFlag(MachineInstr::FrameSetup);
+    TII.storeRegToStackSlot(MBB, MI, I.getReg(), true, I.getFrameIdx(), &SH::GPRRegClass, 0);
   }
   return true;
 }
 
-bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator II,
                                    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
   
   LLVM_DEBUG(dbgs() << "Restoring " << CSI.size() << " registers...\n");
@@ -300,19 +296,12 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
       return false;
   }
 
-  DebugLoc DL = MBB.findDebugLoc(MI);
+  DebugLoc DL = MBB.findDebugLoc(II);
   MachineFunction &MF = *MBB.getParent();
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
-  const SuperHRegisterInfo &RII = *STI.getRegisterInfo();
   const TargetInstrInfo &TII = *STI.getInstrInfo();
-  Register SP = RII.getStackRegister();
-
-  for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
-
-    MCRegister Reg = I.getReg();
-    BuildMI(MBB, MI, DL, TII.get(SH::MOVLM), SP)
-      .addReg(Reg)
-      .setMIFlag(MachineInstr::FrameDestroy);
+  for (const CalleeSavedInfo &I : CSI) {
+    TII.loadRegFromStackSlot(MBB, II, I.getReg(), I.getFrameIdx(), &SH::GPRRegClass, 0);
   }
 
   return true;
@@ -362,4 +351,110 @@ bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
 bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   return hasFP(MF) && !MFI.hasVarSizedObjects();
-}
\ No newline at end of file
+}
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                         Frame Load-Store Fixup Pass
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "sh-frame-fixup"
+
+namespace llvm {
+
+// This pass serves to fix up frame loads and stores after subroutine jumps
+// to ensure that return values are not clobbered.
+struct SuperHFrameFixupPass : public MachineFunctionPass {
+private:
+  const SuperHSubtarget *STI;
+
+public:
+  static char ID;
+  typedef MachineBasicBlock::iterator BlockIt;
+  typedef MachineBasicBlock &Block;
+
+  SuperHFrameFixupPass() : MachineFunctionPass(ID) {}
+
+  // Fixes up JSR instructions so that their return values don't 
+  // get clobbered by the implicit stores done by stack loads
+  // 
+  bool fixupJSR(Block MBB, BlockIt MBII) {
+    LLVM_DEBUG(dbgs() << " - Fixing up JSR instruction...\n");
+    MachineInstr *MP = &*std::next(MBII);
+    int Moved = 0;
+
+    BlockIt II = std::next(MBII), E = MBB.end();
+    while (II != E) {
+      BlockIt NII = std::next(II);
+
+      switch(II->getOpcode()) {
+      case SH::MOVBLPtr:
+      case SH::MOVWLPtr:
+      case SH::MOVLLPtr:
+      case SH::ADJCALLSTACKUP:
+      case SH::NOP: {
+        break;
+      }
+      case SH::COPY: {
+        if (II->readsRegister(SH::R0, nullptr) || II->readsRegister(SH::R1, nullptr)) {
+          II->moveBefore(MP);
+          Moved++;
+        }
+        break;
+      }
+      default: 
+
+        // We've reached a barrier where moving instructions up could be dangerous.
+        // as such, end the MBB pass here.
+        NII = E;
+        break;
+      }
+
+      II = NII;
+    }
+
+    LLVM_DEBUG(dbgs() << " - Moved " << Moved << " instructions in BB.\n");
+    return Moved > 0;
+  }
+
+  bool runOnBasicBlock(Block &MBB) {
+    BlockIt II = MBB.begin(), E = MBB.end();
+    while (II != E) {
+      switch(II->getOpcode()) {
+      default: break;
+      case SH::JSR:
+        return fixupJSR(MBB, II);
+      }
+      II = std::next(II);
+    }
+    return false;
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override {
+    LLVM_DEBUG(dbgs() << "\n********** SuperHFrameFixupPass **********\n");
+    LLVM_DEBUG(dbgs() << "Fixing up " << MF.getName() << "...\n");
+
+    STI = &MF.getSubtarget<SuperHSubtarget>();
+
+    int Modified = 0;
+    for (Block &BB : MF) {
+      Modified += runOnBasicBlock(BB);
+    }
+    LLVM_DEBUG(dbgs() << "Modified " << Modified << " BBs in " << MF.getName() << "...\n\n");
+    return Modified > 0;
+  }
+
+
+  StringRef getPassName() const override { return "SuperH frame load/store fixup pass"; }
+};
+
+char SuperHFrameFixupPass::ID = 0;
+
+/// Creates instance of the frame analyzer pass.
+FunctionPass *createSuperHFrameFixupPass() { return new SuperHFrameFixupPass(); }
+
+} // namespace llvm
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 35cdeb387f5ae..b3fff5b4d8de6 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -15,6 +15,7 @@
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperH.h"
 #include "SuperHConstantPoolValue.h"
+#include "SuperHInstrInfo.h"
 #include "SuperHMachineFunctionInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
@@ -38,31 +39,6 @@ using namespace llvm;
 
 namespace {
 
-struct SHAddressWrapper {
-  enum SHAddrType {
-    GLOBAL_VALUE,
-    CONSTANT,
-    BLOCK,
-    SYM_LOCAL,
-    SYM_EXTERNAL,
-  };
-  SHAddrType Type;
-  SDValue BaseReg;
-  int64_t Disp;
-
-  // Max size of displacement.
-  unsigned DispSize;
-
-  const GlobalValue *GV;
-  const Constant *CP;
-  const BlockAddress *BlockAddr;
-  const char *ES;
-  MCSymbol *MCSym;
-  SHRefClass SymbolFlags; // SHII::MO_*
-
-  SHAddressWrapper(unsigned DS) : DispSize(DS) { }
-};
-
 /// Lowers LLVM IR (in DAG form) to SuperH MC instructions (in DAG form).
 class SuperHDAGToDAGISel : public SelectionDAGISel {
 public:
@@ -135,22 +111,39 @@ bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
 
 bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
                                     SDValue &Disp) {
-  SDLoc dl(Op);
   auto DL = CurDAG->getDataLayout();
   MVT PtrVT = getTargetLowering()->getPointerTy(DL);
-  MachineFunction &MF = CurDAG->getMachineFunction();
-  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
 
   // if the address is a frame index get the TargetFrameIndex.
   if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
-    Disp = CurDAG->getTargetConstant(0, dl, MVT::i8);
+    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
     return true;
   }
 
+  if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+
+    // Handle frame index + offset
+    if (N.getOperand(0).getOpcode() == ISD::FrameIndex) {
+      int RHSC = (int)RHS->getZExtValue();
+      int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
+
+      Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
+      Disp = CurDAG->getTargetConstant(RHSC, SDLoc(Op), MVT::i32);
+      return true;
+    }
+
+    // Handle reg + offset
+    if (N.getOpcode() == ISD::ADD) {
+      Base = N.getOperand(0);
+      Disp = CurDAG->getTargetConstant(RHS->getZExtValue(), SDLoc(Op), MVT::i32);
+      return true;
+    }
+  }
+
   // if the address is a wrapper, get the underlying data.
   if (N.getOpcode() == SHISD::WRAPPER) {
-    Base = N->getOperand(0);
+    Base = N.getOperand(0);
     Disp = N;
     return true;
   }
@@ -225,7 +218,7 @@ template<>
 bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
   SDValue LHS = N->getOperand(0);
   SDValue RHS = N->getOperand(1);
-  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+  SHCC::CondCode CC = (SHCC::CondCode)dyn_cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
   SDLoc DL(N);
 
   // NOTE:  The comparisons just set the T bit, it's up to later instructions
@@ -233,8 +226,7 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
   SDNode *Res = nullptr;
   switch(CC) {
   default: break;
-  case ISD::SETEQ:
-  case ISD::SETNE: {
+  case SHCC::COND_EQ: {
 
     // TST would be faster in this case.
     if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
@@ -246,24 +238,28 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
     Res = CurDAG->getMachineNode(SH::CMPEQ, DL, MVT::Glue, LHS, RHS);
     break;
   }
-  case ISD::SETUGE:
-  case ISD::SETULT: {
-    Res = CurDAG->getMachineNode(SH::CMPHS, DL, MVT::Glue, LHS, RHS);
+  case SHCC::COND_GT: {
+    Res = CurDAG->getMachineNode(SH::CMPGT, DL, MVT::Glue, LHS, RHS);
     break;
   }
-  case ISD::SETOGE:
-  case ISD::SETOLT: {
+  case SHCC::COND_GE: {
     Res = CurDAG->getMachineNode(SH::CMPGE, DL, MVT::Glue, LHS, RHS);
     break;
   }
-  case ISD::SETUGT:
-  case ISD::SETULE: {
-    Res = CurDAG->getMachineNode(SH::CMPGT, DL, MVT::Glue, LHS, RHS);
+  case SHCC::COND_HI: {
+    Res = CurDAG->getMachineNode(SH::CMPHI, DL, MVT::Glue, LHS, RHS);
     break;
   }
-  case ISD::SETOGT:
-  case ISD::SETOLE: {
-    Res = CurDAG->getMachineNode(SH::CMPHI, DL, MVT::Glue, LHS, RHS);
+  case SHCC::COND_HS: {
+    Res = CurDAG->getMachineNode(SH::CMPHS, DL, MVT::Glue, LHS, RHS);
+    break;
+  }
+  case SHCC::COND_PL: {
+    Res = CurDAG->getMachineNode(SH::CMPPL, DL, MVT::Glue, LHS, RHS);
+    break;
+  }
+  case SHCC::COND_PZ: {
+    Res = CurDAG->getMachineNode(SH::CMPPZ, DL, MVT::Glue, LHS, RHS);
     break;
   }
   }
@@ -281,7 +277,7 @@ template<>
 bool SuperHDAGToDAGISel::trySelect<SHISD::BRCOND>(SDNode *N) {
   SDValue Chain = N->getOperand(0);
   SDValue Dest = N->getOperand(1);
-  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+  SHCC::CondCode CC = (SHCC::CondCode)dyn_cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
   SDValue Cmp = N->getOperand(3);
   SDLoc DL(N);
 
@@ -290,19 +286,11 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::BRCOND>(SDNode *N) {
   MachineSDNode *Res = nullptr;
   switch(CC) {
   default: break;
-  case ISD::SETEQ:
-  case ISD::SETUGE:
-  case ISD::SETOGE:
-  case ISD::SETUGT:
-  case ISD::SETOGT:
+  case SHCC::COND_T:
     Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BTS : SH::BT, 
           DL, MVT::Other, Dest, Chain, Cmp);
     break;
-  case ISD::SETNE:
-  case ISD::SETULE:
-  case ISD::SETOLE:
-  case ISD::SETULT:
-  case ISD::SETOLT:
+  case SHCC::COND_F:
     Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BFS : SH::BF, 
           DL, MVT::Other, Dest, Chain, Cmp);
     break;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 9f8da36d6c795..d378a6878e196 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -21,6 +21,7 @@
 #include "SuperHRegisterInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
@@ -42,20 +43,6 @@ using namespace llvm;
 
 #define DEBUG_FN_PRINT() LLVM_DEBUG(dbgs() << " - " << __PRETTY_FUNCTION__ << "\n");
 
-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)
@@ -129,6 +116,31 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setMinStackArgumentAlignment(Align(4));
 }
 
+
+
+
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+//                            CALLING CONVENTIONS
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+static bool RetCC_SH_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"
+
+
+
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 //                                LOWERING
@@ -143,8 +155,89 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
 //                        CONDITIONAL BRANCH LOWERING
 //===----------------------------------------------------------------------===//
 SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
-                                       SelectionDAG &DAG, SDLoc DL) const {
-  return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, DAG.getCondCode(CC));
+                                       SDValue &OutCC, SelectionDAG &DAG, 
+                                       SDLoc DL) const {
+  SDValue InCC;
+  SHCC::CondCode SHcc = SHCC::COND_INVALID;
+  SHCC::CondCode SHocc = SHCC::COND_T;
+
+  switch(CC) {
+  default: break;
+  case ISD::SETEQ: {
+    SHcc = SHCC::COND_EQ;
+    SHocc = SHCC::COND_T;
+    break;
+  }
+  case ISD::SETNE: {
+    SHcc = SHCC::COND_EQ;
+    SHocc = SHCC::COND_F;
+    break;
+  }
+  case ISD::SETLT: {
+    // Swap operands and reverse the branching condition.
+    std::swap(LHS, RHS);
+    SHcc = SHCC::COND_GE;
+    SHocc = SHCC::COND_T;
+    break;
+  }
+  case ISD::SETLE: {
+    // Swap operands and reverse the branching condition.
+    std::swap(LHS, RHS);
+    SHcc = SHCC::COND_GT;
+    SHocc = SHCC::COND_T;
+    break;
+  }
+  case ISD::SETGT: {
+    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
+      switch (C->getSExtValue()) {
+      case -1: {
+        SHcc = SHCC::COND_PZ;
+        SHocc = SHCC::COND_T;
+        break;
+      }
+      case 0: {
+        SHcc = SHCC::COND_PL;
+        SHocc = SHCC::COND_T;
+        break;
+      }
+      }
+    }
+    break;
+  }
+  case ISD::SETGE: {
+    SHcc = SHCC::COND_GE;
+    SHocc = SHCC::COND_T;
+    break;
+  }
+  case ISD::SETUGT: {
+    SHcc = SHCC::COND_HI;
+    SHocc = SHCC::COND_T;
+    break;
+  }
+  case ISD::SETUGE: {
+    SHcc = SHCC::COND_HS;
+    SHocc = SHCC::COND_T;
+    break;
+  }
+  case ISD::SETULT: {
+    // Swap operands and reverse the branching condition.
+    std::swap(LHS, RHS);
+    SHcc = SHCC::COND_HS;
+    SHocc = SHCC::COND_T;
+    break;
+  }
+  case ISD::SETULE: {
+    // Swap operands and reverse the branching condition.
+    std::swap(LHS, RHS);
+    SHcc = SHCC::COND_HI;
+    SHocc = SHCC::COND_T;
+    break;
+  }
+  }
+
+  InCC = DAG.getTargetConstant(SHcc, DL, MVT::i8);
+  OutCC = DAG.getTargetConstant(SHocc, DL, MVT::i8);
+  return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, InCC);
 }
 
 SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
@@ -155,8 +248,8 @@ SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) cons
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
   SDLoc DL(Op);
 
-  SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
-  SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i8);
+  SDValue TargetCC;
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
 
   SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
   return DAG.getNode(SHISD::SELECT_CC, DL, Op.getValueType(), Ops);
@@ -168,12 +261,13 @@ SDValue SuperHTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
   SDLoc DL(Op);
 
-  SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
-  SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i8);
+  SDValue TargetCC;
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
 
   SDValue TrueV = DAG.getConstant(1, DL, Op.getValueType());
   SDValue FalseV = DAG.getConstant(0, DL, Op.getValueType());
   SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
+
   return DAG.getNode(SHISD::SELECT_CC, DL, Op.getValueType(), Ops);
 }
 
@@ -187,10 +281,11 @@ SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
   SDValue Dest = Op.getOperand(4);
   SDLoc DL(Op);
 
-  SDValue Cmp = getSHCmp(LHS, RHS, CC, DAG, DL);
-  SDValue TargetCC = DAG.getCondCode(CC);
+  SDValue TargetCC;
+  SDValue Cmp = getSHCmp(LHS, RHS, CC, TargetCC, DAG, DL);
+  SDValue Ops[] = {Chain, Dest, TargetCC, Cmp};
 
-  return DAG.getNode(SHISD::BRCOND, DL, MVT::Other, Chain, Dest, TargetCC, Cmp);
+  return DAG.getNode(SHISD::BRCOND, DL, MVT::Other, Ops);
 }
 
 
@@ -314,6 +409,7 @@ SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) c
 //                             ARGUMENT LOWERING
 //===----------------------------------------------------------------------===//
 
+
 SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
                        CallingConv::ID CallConv, bool IsVarArg,
                        const SmallVectorImpl<ISD::InputArg> &Ins,
@@ -362,16 +458,16 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
       case CCValAssign::SExt:
         ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,
                                DAG.getValueType(VA.getValVT()));
-        ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
         break;
       case CCValAssign::ZExt:
         ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,
                                DAG.getValueType(VA.getValVT()));
-        ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
         break;
       }
 
-      InVals.push_back(ArgValue);
+      if (VA.isExtInLoc()) {
+        ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
+      }
     } else {
 
       // Only arguments passed on the stack should make it here.
@@ -385,9 +481,16 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
       // 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)));
+      ArgValue = DAG.getLoad(LocVT, dl, Chain, FIN, 
+                             MachinePointerInfo::getFixedStack(MF, FI));
     }
+
+    // If value is passed via pointer - do a load.
+    if (VA.getLocInfo() == CCValAssign::Indirect)
+      ArgValue =
+          DAG.getLoad(VA.getValVT(), dl, Chain, ArgValue, MachinePointerInfo());
+
+    InVals.push_back(ArgValue);
   }
 
   // TODO: Handle varargs.
@@ -494,6 +597,7 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
   SmallVector<CCValAssign, 16> ArgLocs;
   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
                  *DAG.getContext());
+  CCInfo.AnalyzeCallOperands(Outs, CC_SH);
 
   // Resolve the global value to jump to.
   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
@@ -501,7 +605,6 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
   } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
     Callee = LowerExternalSymbol(SDValue(S, 0), DAG);
   }
-  CCInfo.AnalyzeCallOperands(Outs, CC_SH);
 
   // Get a count of how many bytes are to be pushed on the stack.
   unsigned NumBytes = CCInfo.getStackSize();
@@ -534,6 +637,16 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
     case CCValAssign::BCvt:
       Arg = DAG.getNode(ISD::BITCAST, DL, RegVT, Arg);
       break;
+    case CCValAssign::Indirect: {
+      // Store the argument.
+      SDValue SpillSlot = DAG.CreateStackTemporary(VA.getValVT());
+      int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
+      Chain = DAG.getStore(
+          Chain, DL, Arg, SpillSlot,
+          MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));
+      Arg = SpillSlot;
+      break;
+    }
     }
 
     // Stop when we encounter a stack argument, we need to process them
@@ -566,7 +679,7 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
       SDValue PtrOff = DAG.getNode(
           ISD::ADD, DL, getPointerTy(DAG.getDataLayout()),
           DAG.getRegister(SH::R15, getPointerTy(DAG.getDataLayout())),
-          DAG.getIntPtrConstant(VA.getLocMemOffset() + 1, DL));
+          DAG.getIntPtrConstant(VA.getLocMemOffset() + 4, DL));
 
       MemOpChains.push_back(
           DAG.getStore(Chain, DL, Arg, PtrOff,
@@ -632,12 +745,32 @@ SDValue SuperHTargetLowering::LowerCallResult(
   CCInfo.AnalyzeCallResult(Ins, RetCC_SH);
 
   // Copy all of the result registers out of their specified physreg.
-  for (CCValAssign const &RVLoc : RVLocs) {
-    Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(), InGlue)
-                .getValue(1);
-
+  for (CCValAssign const &VA : RVLocs) {
+    SDValue RV;
+    RV = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), InGlue);
+    Chain = RV.getValue(1);
     InGlue = Chain.getValue(2);
-    InVals.push_back(Chain.getValue(0));
+
+    // The callee promoted the return value, so insert an Assert?ext SDNode so
+    // we won't promote the value again in this function.
+    switch (VA.getLocInfo()) {
+    case CCValAssign::SExt:
+      RV = DAG.getNode(ISD::AssertSext, dl, VA.getLocVT(), RV,
+                       DAG.getValueType(VA.getValVT()));
+      break;
+    case CCValAssign::ZExt:
+      RV = DAG.getNode(ISD::AssertZext, dl, VA.getLocVT(), RV,
+                       DAG.getValueType(VA.getValVT()));
+      break;
+    default:
+      break;
+    }
+
+    // Truncate the register down to the return value type.
+    if (VA.isExtInLoc())
+      RV = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RV);
+
+    InVals.push_back(RV);
   }
 
   return Chain;
@@ -832,7 +965,7 @@ MachineBasicBlock *SuperHTargetLowering::insertSELECTCC(MachineInstr &MI,
 
   MachineOperand TrueV = MI.getOperand(0);
   MachineOperand FalseV = MI.getOperand(1);
-  ISD::CondCode CC = (ISD::CondCode)MI.getOperand(3).getImm();
+  SHCC::CondCode CC = (SHCC::CondCode)MI.getOperand(3).getImm();
 
   // Lower True-False selection
   if (TrueV.isImm() && FalseV.isImm()) {
@@ -883,7 +1016,7 @@ MachineBasicBlock *SuperHTargetLowering::insertSELECTCC(MachineInstr &MI,
                   std::next(MachineBasicBlock::iterator(MI)), MBB->end());
   trueMBB->transferSuccessorsAndUpdatePHIs(MBB);
 
-  BuildMI(MBB, DL, TII.getBrCond(CC)).addMBB(trueMBB);
+  BuildMI(MBB, DL, TII.getBrCond(CC, false)).addMBB(trueMBB);
   BuildMI(MBB, DL, TII.get(SH::BRA)).addMBB(falseMBB);
   MBB->addSuccessor(falseMBB);
   MBB->addSuccessor(trueMBB);
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 7b6a9d88006b5..5b66a6b9ca725 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -15,6 +15,7 @@
 #define LLVM_LIB_TARGET_SUPERH_SUPERHISELLOWERING_H
 
 #include "SuperH.h"
+#include "SuperHInstrInfo.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/IR/GlobalValue.h"
@@ -78,7 +79,7 @@ class SuperHTargetLowering : public TargetLowering  {
   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
   SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
-                   SelectionDAG &DAG, SDLoc DL) const;
+                   SDValue &OutCC, SelectionDAG &DAG, SDLoc DL) const;
 
   // Inserters
   MachineBasicBlock *
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 2dad985974518..c144341f3b126 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -12,12 +12,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "SuperHInstrInfo.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperHRegisterInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
 #include "MCTargetDesc/SuperHInstPrinter.h"
 #include "SuperH.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -72,45 +74,36 @@ void SuperHInstrInfo::insertNoop(MachineBasicBlock &MBB,
   BuildMI(&MBB, MI->getDebugLoc(), get(SH::NOP));
 }
 
-ISD::CondCode SuperHInstrInfo::getCondFromBranchOp(unsigned Op) const {
+SHCC::CondCode SuperHInstrInfo::getCondFromBranchOp(unsigned Op) const {
   switch (Op) {
   default:
-    return ISD::SETCC_INVALID;
+    return SHCC::COND_INVALID;
   case SH::NOP:
   case SH::BT:
   case SH::BTS:
-    return ISD::SETTRUE;
+    return SHCC::COND_T;
   case SH::BF:
   case SH::BFS:
-    return ISD::SETFALSE;
+    return SHCC::COND_F;
   }
 }
 
-ISD::CondCode SuperHInstrInfo::getOppositeCondCode(ISD::CondCode Op) const {
+SHCC::CondCode SuperHInstrInfo::getOppositeCondCode(SHCC::CondCode Op) const {
   switch (Op) {
-  default:
-    return ISD::SETCC_INVALID;
-  case ISD::SETTRUE:
-    return ISD::SETFALSE;
-  case ISD::SETFALSE:
-    return ISD::SETTRUE;
+  default:              return SHCC::COND_INVALID;
+  case SHCC::COND_T:    return SHCC::COND_F;
+  case SHCC::COND_F:    return SHCC::COND_T;
   }
 }
 
-const MCInstrDesc &SuperHInstrInfo::getBrCond(ISD::CondCode CC) const {
+const MCInstrDesc &SuperHInstrInfo::getBrCond(SHCC::CondCode CC, bool delaySlot) const {
   switch (CC) {
   default:
     llvm_unreachable("Unknown condition code!");
-  case ISD::SETTRUE:
-  case ISD::SETEQ:
-  case ISD::SETGT:
-  case ISD::SETGE:
-    return get(SH::BT);
-  case ISD::SETFALSE:
-  case ISD::SETNE:
-  case ISD::SETLT:
-  case ISD::SETLE:
-    return get(SH::BF);
+  case SHCC::COND_T:
+    return get(delaySlot ? SH::BTS : SH::BT);
+  case SHCC::COND_F:
+    return get(delaySlot ? SH::BFS : SH::BF);
   }
 }
 
@@ -186,106 +179,84 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 //                              Stack Frames
 //===----------------------------------------------------------------------===//
 
+Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+  if (MI.getOperand(0).isReg() && MI.getOperand(1).isFI() &&
+      MI.getOperand(2).getImm() == 0) {
+    FrameIndex = MI.getOperand(1).getIndex();
+    return MI.getOperand(0).getReg();
+  }
+  return 0;
+}
+
 void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, 
                                           Register SrcReg, bool isKill, int FrameIndex, 
                                           const TargetRegisterClass *RC, Register VReg, 
                                           MachineInstr::MIFlag Flags) const {
-
-  MachineInstr &MI = *II;
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   uint ObjectSize = MFI.getObjectSize(FrameIndex);
-  DebugLoc DL = MI.getDebugLoc();
 
-  LLVM_DEBUG(dbgs() << "Store " << RI.getName(SrcReg) 
+  LLVM_DEBUG(dbgs() << "Store " << (SrcReg > RI.getNumRegs() ? "VREG" : RI.getName(SrcReg)) 
                     << " to slot " << FrameIndex
                     << " size=" << ObjectSize << "\n");
 
+  unsigned Opc;
   switch(ObjectSize) {
   default: llvm_unreachable("Cannot store this register into stack slot!");
-  case 1: {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVBSPtr))
-      .addReg(SrcReg, getKillRegState(isKill))
-      .addFrameIndex(FrameIndex)
-      .addImm(0);
+  case 1:
+    Opc = SH::MOVBSPtr;
     break;
-  }
-  case 2: {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVWSPtr))
-      .addReg(SrcReg, getKillRegState(isKill))
-      .addFrameIndex(FrameIndex)
-      .addImm(0);
+  case 2:
+    Opc = SH::MOVWSPtr;
     break;
-  }
-  case 4: {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVLSPtr))
-      .addReg(SrcReg, getKillRegState(isKill))
-      .addFrameIndex(FrameIndex)
-      .addImm(0);
+  case 4:
+    Opc = SH::MOVLSPtr;
     break;
   }
+  BuildMI(MBB, II, DebugLoc(), get(Opc))
+    .addReg(SrcReg, getKillRegState(isKill))
+    .addFrameIndex(FrameIndex)
+    .addImm(0);
+}
+
+Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+  if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() && 
+      MI.getOperand(1).getImm() == 0) {
+    FrameIndex = MI.getOperand(0).getIndex();
+    return MI.getOperand(2).getReg();
   }
+  return 0;
 }
 
 void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, 
                                            Register DestReg, int FrameIndex, 
                                            const TargetRegisterClass *RC, Register VReg,
                                            unsigned SubReg, MachineInstr::MIFlag Flags) const {
-
-  MachineInstr &MI = *II;
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   uint ObjectSize = MFI.getObjectSize(FrameIndex);
-  DebugLoc DL = MI.getDebugLoc();
-
-  // HACK: This is ugly but it works.. somehow.
-  II = std::next(II);
-  II = std::next(II);
 
-  LLVM_DEBUG(dbgs() << "Load " << RI.getName(DestReg) 
+  LLVM_DEBUG(dbgs() << "Load " << (DestReg > RI.getNumRegs() ? "VREG" : RI.getName(DestReg)) 
                     << " from slot " << FrameIndex
                     << " size=" << ObjectSize << "\n");
-
+  
+  unsigned Opc;
   switch(ObjectSize) {
   default: llvm_unreachable("Cannot load this register from stack slot!");
-  case 1: {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVBLPtr), DestReg)
-      .addFrameIndex(FrameIndex)
-      .addImm(0);
+  case 1:
+    Opc = SH::MOVBLPtr;
     break;
-  }
-
-  case 2: {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVWLPtr), DestReg)
-      .addFrameIndex(FrameIndex)
-      .addImm(0);
+  case 2:
+    Opc = SH::MOVWLPtr;
     break;
-  }
-  case 4: {
-    BuildMI(MBB, II, DebugLoc(), get(SH::MOVLLPtr), DestReg)
-      .addFrameIndex(FrameIndex)
-      .addImm(0);
+  case 4:
+    Opc = SH::MOVLLPtr;
     break;
   }
-  }
-}
-
-Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
-  if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
-      MI.getOperand(2).getImm() == 0) {
-    FrameIndex = MI.getOperand(1).getIndex();
-    return MI.getOperand(0).getReg();
-  }
-  return 0;
-}
 
-Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const {
-  if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
-      MI.getOperand(1).getImm() == 0) {
-    FrameIndex = MI.getOperand(0).getIndex();
-    return MI.getOperand(2).getReg();
-  }
-  return 0;
+  BuildMI(MBB, II, DebugLoc(), get(Opc), DestReg)
+    .addFrameIndex(FrameIndex)
+    .addImm(0);
 }
 
 
@@ -351,8 +322,8 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
     }
 
     // Handle conditional branches.
-    ISD::CondCode BranchCode = getCondFromBranchOp(I->getOpcode());
-    if (BranchCode == ISD::SETCC_INVALID) {
+    SHCC::CondCode BranchCode = getCondFromBranchOp(I->getOpcode());
+    if (BranchCode == SHCC::COND_INVALID) {
       return true; // Can't handle indirect branch.
     }
 
@@ -363,7 +334,7 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
           MBB.isLayoutSuccessor(TargetBB)) {
 
         BranchCode = getOppositeCondCode(BranchCode);
-        auto JNCC = getBrCond(BranchCode);
+        auto JNCC = getBrCond(BranchCode, false);
 
         MachineBasicBlock::iterator OldInst = I;
         BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), JNCC)
@@ -397,7 +368,7 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
       return true;
     }
 
-    ISD::CondCode OldBranchCode = (ISD::CondCode)Cond[0].getImm();
+    SHCC::CondCode OldBranchCode = (SHCC::CondCode)Cond[0].getImm();
     // If the conditions are the same, we can leave them alone.
     if (OldBranchCode == BranchCode) {
       continue;
@@ -431,8 +402,8 @@ unsigned SuperHInstrInfo::insertBranch(MachineBasicBlock &MBB, MachineBasicBlock
 
   // Conditional branch.
   unsigned Count = 0;
-  ISD::CondCode CC = (ISD::CondCode)Cond[0].getImm();
-  auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
+  SHCC::CondCode CC = (SHCC::CondCode)Cond[0].getImm();
+  auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC, false)).addMBB(TBB);
 
   if (BytesAdded)
     *BytesAdded += getInstSizeInBytes(CondMI);
@@ -483,7 +454,7 @@ bool
 SuperHInstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
   assert(Cond.size() == 1 && "Invalid SH branch condition!");
 
-  ISD::CondCode CC = static_cast<ISD::CondCode>(Cond[0].getImm());
+  SHCC::CondCode CC = (SHCC::CondCode)Cond[0].getImm();
   Cond[0].setImm(getOppositeCondCode(CC));
   return false;
 }
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 78656e8b07db9..a944d2089df1b 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -15,6 +15,7 @@
 #define LLVM_LIB_TARGET_SUPERH_SUPERHINSTRINFO_H
 
 #include "SuperHRegisterInfo.h"
+#include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
@@ -23,6 +24,27 @@
 #include "SuperHGenInstrInfo.inc"
 
 namespace llvm {
+class SuperHSubtarget;
+
+namespace SHCC {
+
+/// SuperH specific condition codes.
+/// These correspond to `SH_*_COND` in `SuperHInstrInfo.td`.
+/// They must be kept in sync.
+enum CondCode {
+  COND_EQ, //!< Equal
+  COND_GT, //!< Greater than
+  COND_GE, //!< Greater than or equal
+  COND_HI, //!< Higher than
+  COND_HS, //!< Higher than or same
+  COND_PL, //!< Greater than 0
+  COND_PZ, //!< Greater than or equal to 0
+  COND_T,  //!< True
+  COND_F,  //!< False
+  COND_INVALID
+};
+
+} // end of namespace SHCC
 
 class SuperHInstrInfo : public SuperHGenInstrInfo {
   const SuperHRegisterInfo RI;
@@ -43,9 +65,9 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   /// in a delay slot, nor does it allow instructions with delay slots
   /// to be chained together.
   bool canFillDelaySlot(unsigned Opcode) const;
-  ISD::CondCode getCondFromBranchOp(unsigned Op) const;
-  ISD::CondCode getOppositeCondCode(ISD::CondCode CC) const;
-  const MCInstrDesc &getBrCond(ISD::CondCode CC) const;
+  SHCC::CondCode getCondFromBranchOp(unsigned Op) const;
+  SHCC::CondCode getOppositeCondCode(SHCC::CondCode CC) const;
+  const MCInstrDesc &getBrCond(SHCC::CondCode CC, bool delaySlot) const;
 
   // Instruction Info
   unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
@@ -76,6 +98,7 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   Register isStoreToStackSlot(const MachineInstr &MI,
                               int &FrameIndex) const override;
 
+
   // Branch Analysis
   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
                      MachineBasicBlock *&FBB,
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 1af8a591b5458..7b64a55e56cf3 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -50,8 +50,8 @@ def SHSDT_CallSeqEnd    : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
 def SHSDT_Call          : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
 def SHSDT_PICAdd        : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
                                           SDTCisPtrTy<1>, SDTCisVT<2, i32>]>;
-def SHSDT_Brcond        : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, OtherVT>]>;
-def SHSDT_Cmp           : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, OtherVT>]>;
+def SHSDT_Brcond        : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i8>]>;
+def SHSDT_Cmp           : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, i8>]>;
 def SHSDT_SelectCC      : SDTypeProfile<1, 3, 
                           [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i8>]>;
 
@@ -236,6 +236,8 @@ let WantsRoot = true in
 def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
 
 
+
+
 //===--------------------------------------------------------------------------===//
 // Predicates
 //===--------------------------------------------------------------------------===//
@@ -274,6 +276,26 @@ def HasSH4A     : Predicate<"Subtarget->hasSH4AInst()">,
                   AssemblerPredicate<(all_of FeatureSH4A)>;  
 
 
+
+
+//===--------------------------------------------------------------------------===//
+// Condition Codes
+//===--------------------------------------------------------------------------===//
+// NOTE:  To assist codegen, condition codes are created 
+//        for pseudo instructions.
+//===--------------------------------------------------------------------------===//
+
+def SH_COND_EQ : PatLeaf<(i8 0)>;
+def SH_COND_GT : PatLeaf<(i8 1)>;
+def SH_COND_GE : PatLeaf<(i8 2)>;
+def SH_COND_HI : PatLeaf<(i8 3)>;
+def SH_COND_HS : PatLeaf<(i8 4)>;
+def SH_COND_PL : PatLeaf<(i8 5)>;
+def SH_COND_PZ : PatLeaf<(i8 6)>;
+
+
+
+
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 //                          Data Transfer Instructions
@@ -1380,6 +1402,27 @@ include "SuperHInstrDSP.td"
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
 
+//===--------------------------------------------------------------------------===//
+// Conditional Branching
+//===--------------------------------------------------------------------------===//
+// NOTE:  SuperH only has BT (Branch if True) and BF (Branch if False)
+//        as such we'll lower these to pseudo instructions instead, then
+//        later emit real machine code instructions from them.
+//        Additionally, conditional branch sequences can be multiple
+//        instructions long, which can wreak havoc with the LLVM branch
+//        handling.
+//===--------------------------------------------------------------------------===//
+
+let isBranch = 1, isTerminator = 1, Uses = [SR] in {
+def BRCC       : SHPseudo<(outs), (ins brtarget:$disp, i8imm:$cc),
+                          "! BREQ $disp, $cc",
+                          [/*(SHbrcond bb:$disp, i8:$cc)*/]>;
+}
+
+
+
+
+
 //===--------------------------------------------------------------------------===//
 // SelectCC & SetCC
 //===--------------------------------------------------------------------------===//
@@ -1388,52 +1431,61 @@ def Select8     : SHSelectPseudo<(outs GPR:$dst),
                                 (ins GPR:$src, GPR:$src2, i8imm:$cc),
                                 "; Select8 PSEUDO",
                                 [(set i8:$dst,
-                                 (SHselectcc i8:$src, i8:$src2, imm:$cc))]>;
+                                 (SHselectcc i8:$src, i8:$src2, timm:$cc))]>;
 
 def Select16    : SHSelectPseudo<(outs GPR:$dst),
                                 (ins GPR:$src, GPR:$src2, i8imm:$cc),
                                 "; Select16 PSEUDO",
                                 [(set i16:$dst,
-                                 (SHselectcc i16:$src, i16:$src2, imm:$cc))]>;
+                                 (SHselectcc i16:$src, i16:$src2, timm:$cc))]>;
 
 def Select32    : SHSelectPseudo<(outs GPR:$dst),
                                 (ins GPR:$src, GPR:$src2, i8imm:$cc),
                                 "; Select32 PSEUDO",
                                 [(set i32:$dst,
-                                 (SHselectcc i32:$src, i32:$src2, imm:$cc))]>;
+                                 (SHselectcc i32:$src, i32:$src2, timm:$cc))]>;
 
 //===--------------------------------------------------------------------------===//
 // Frame Load/Store
 //===--------------------------------------------------------------------------===//
 
 // LOAD FROM ADDRESS
-let mayLoad = 1, Defs = [R0, R1], Uses = [R0, R1] in {
+let mayLoad = 1, isReMaterializable = 1 in {
+
+let Defs = [R0, R1] in
 def MOVBLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                             "! MOVBLPtr $src, $Rn",
                             []>;
 
+let Defs = [R0, R1] in
 def MOVWLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                             "! MOVWLPtr $src, $Rn",
                             []>;
 
+let Defs = [R1] in
 def MOVLLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                             "! MOVLLPtr $src, $Rn",
                             []>;
 }
 
 // STORE TO ADDRESS
-let mayStore = 1, Defs = [R0, R1], Uses = [R0, R1] in {
+let mayStore = 1, isReMaterializable = 1 in {
+
+let Defs = [R0, R1] in
 def MOVBSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                              "! MOVBSPtr $src, $dst",
                              [(truncstorei8 i32:$src, addr:$dst)]>;
 
+let Defs = [R0, R1] in
 def MOVWSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                              "! MOVWSPtr $src, $dst",
                              [(truncstorei16 i32:$src, addr:$dst)]>;
 
+let Defs = [R1] in
 def MOVLSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                              "! MOVLSPtr $src, $dst",
                              [(store i32:$src, addr:$dst)]>;
+
 }
 
 
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index a1ed734beedb1..119031c530ccf 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -52,6 +52,10 @@ const uint32_t *SuperHRegisterInfo::getCallPreservedMask(const MachineFunction &
   return CSR_SH_RegMask; 
 }
 
+const uint32_t *SuperHRegisterInfo::getNoPreservedMask() const {
+  return CSR_SH_RegMask; 
+}
+
 const TargetRegisterClass *
 SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
                                            const MachineFunction &MF) const {
@@ -133,7 +137,8 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
 }
 
 Register SuperHRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
-  return SH::R14;
+  const TargetFrameLowering *TFI = getFrameLowering(MF);
+  return TFI->hasFP(MF) ? SH::R14 : SH::R15;
 }
 
 Register SuperHRegisterInfo::getFrameRegister() const {
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index 1c7c1f52fea51..921d966aee4b0 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -31,6 +31,7 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
 
   const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
   const uint32_t *getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const override;
+  const uint32_t *getNoPreservedMask() const override;
   const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const override;
   BitVector getReservedRegs(const MachineFunction &MF) const override;
   const TargetRegisterClass *getLargestLegalSuperClass(const TargetRegisterClass *RC,
@@ -41,6 +42,9 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
                            unsigned FIOperandNum,
                            RegScavenger *RS = nullptr) const override;
 
+  bool requiresRegisterScavenging(const MachineFunction &MF) const override { return true; }
+
+
   // Helpers
   Register getFrameRegister() const;
   Register getStackRegister() const;
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.h b/llvm/lib/Target/SuperH/SuperHSubtarget.h
index d3e767935ada7..a6aa38aaf98c8 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.h
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.h
@@ -67,6 +67,7 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
   const SuperHSelectionDAGInfo *getSelectionDAGInfo() const override { return &TSInfo; }
   const SuperHTargetLowering *getTargetLowering() const override { return &TLInfo; }
 
+  bool isLittleEndian() const { return getTargetTriple().isLittleEndian(); }
   bool isTargetELF() const { return getTargetTriple().isOSBinFormatELF(); }
   bool isPositionIndependent() const { return TM.isPositionIndependent(); }
 
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 18dd3cfc1e7e0..4dcced86224f3 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -49,7 +49,7 @@ class SuperHPassConfig : public TargetPassConfig {
     : TargetPassConfig(TM, PM) {}
 
   bool addInstSelector() override;
-  void addPreSched2() override;
+  void addPostRegAlloc() override;
   void addPreEmitPass2() override;
   SuperHTargetMachine &getSuperHTargetMachine() const {
     return getTM<SuperHTargetMachine>();
@@ -61,7 +61,8 @@ bool SuperHPassConfig::addInstSelector() {
   return false;
 }
 
-void SuperHPassConfig::addPreSched2() {
+void SuperHPassConfig::addPostRegAlloc() {
+  addPass(createSuperHFrameFixupPass());
 }
 
 void SuperHPassConfig::addPreEmitPass2() {

>From 9bd3f290e48ded9a3a98d52df6cb2e5703b5d41a Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 14 Sep 2026 09:25:16 +0200
Subject: [PATCH 48/67] remove printf debugging

---
 llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index 2d69d0859cde6..87d2f14534c51 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -112,9 +112,6 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
   const MachineFunction &MF = *MBB.getParent();
   MachineInstr &MI = *MBBI;
 
-  MI.dump();
-  dbgs() << "\n";
-
   auto SrcReg = MI.getOperand(0).getReg();
   bool SrcIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();

>From b1bd1ea4d27a5daab3247bc78093d9c807c90fac Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 14 Sep 2026 09:36:34 +0200
Subject: [PATCH 49/67] Fix comment

---
 llvm/lib/Target/SuperH/SuperHFrameLowering.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 2721e9e614112..7ef5be9305863 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -380,8 +380,8 @@ struct SuperHFrameFixupPass : public MachineFunctionPass {
   SuperHFrameFixupPass() : MachineFunctionPass(ID) {}
 
   // Fixes up JSR instructions so that their return values don't 
-  // get clobbered by the implicit stores done by stack loads
-  // 
+  // get clobbered by the implicit uses of R0 and R1 done by stack 
+  // loads.
   bool fixupJSR(Block MBB, BlockIt MBII) {
     LLVM_DEBUG(dbgs() << " - Fixing up JSR instruction...\n");
     MachineInstr *MP = &*std::next(MBII);

>From 49fb2cf6bfe3ca43f5a3053226ff77422873e4ec Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 16 Sep 2026 14:33:12 +0200
Subject: [PATCH 50/67] Update codebase to work with rebased upstream

---
 clang/lib/Basic/Targets/SuperH.cpp               |  2 +-
 clang/lib/Basic/Targets/SuperH.h                 |  2 +-
 llvm/include/llvm/IR/RuntimeLibcalls.td          |  3 ++-
 .../SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp      |  1 -
 llvm/lib/Target/SuperH/SuperHFrameLowering.cpp   |  2 +-
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp    |  1 +
 llvm/lib/Target/SuperH/SuperHSubtarget.cpp       | 16 +++++++---------
 llvm/lib/Target/SuperH/SuperHSubtarget.h         |  5 ++---
 llvm/lib/Target/SuperH/SuperHTargetMachine.cpp   |  9 ++-------
 9 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/clang/lib/Basic/Targets/SuperH.cpp b/clang/lib/Basic/Targets/SuperH.cpp
index 2aa91c1a2fea1..62387f6515cfe 100644
--- a/clang/lib/Basic/Targets/SuperH.cpp
+++ b/clang/lib/Basic/Targets/SuperH.cpp
@@ -40,7 +40,7 @@ void SuperHTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) cons
     Values.push_back(Info.Name);
 }
 
-bool SuperHTargetInfo::setCPU(const std::string &Name) {
+bool SuperHTargetInfo::setCPU(StringRef 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; });
diff --git a/clang/lib/Basic/Targets/SuperH.h b/clang/lib/Basic/Targets/SuperH.h
index 2f96a6895c7d3..974ea928e47e3 100644
--- a/clang/lib/Basic/Targets/SuperH.h
+++ b/clang/lib/Basic/Targets/SuperH.h
@@ -94,7 +94,7 @@ class LLVM_LIBRARY_VISIBILITY SuperHTargetInfo : public TargetInfo {
 
   bool isValidCPUName(StringRef Name) const override;
   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
-  bool setCPU(const std::string &Name) override;
+  bool setCPU(StringRef Name) override;
   std::optional<std::string> handleAsmEscapedChar(char EscChar) const override;
   StringRef getABI() const override { return ABI; }
 
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index bca71605a921b..9a72dee557de8 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -84,6 +84,7 @@ def IsRISCV64 : LibcallPredicate<[{TT.isRISCV64()}]>;
 def IsSPARC : LibcallPredicate<[{TT.isSPARC()}]>;
 def IsSPARC32 : LibcallPredicate<[{TT.isSPARC32()}]>;
 def IsSPARC64 : LibcallPredicate<[{TT.isSPARC64()}]>;
+def IsSuperH : LibcallPredicate<[{TT.isSuperH()}]>;
 def IsSPIRV : LibcallPredicate<[{TT.isSPIRV()}]>;
 
 def IsX86_32 : LibcallPredicate<[{TT.getArch() == Triple::x86}]>;
@@ -3402,7 +3403,7 @@ defvar SuperH_DivCalls = [
   __divqi3, __divhi3, __divsi3, __udivqi3, __udivhi3, __udivsi3
 ];
 
-def isSuperH : RuntimeLibcallPredicate<"TT.isSuperH()">;
+def isSuperH : RuntimeLibcallAvailability<(all_of IsSuperH)>;
 def SuperHSystemLibrary 
       : SystemRuntimeLibrary<isSuperH,
                             (add (sub DefaultLibcallImpls32, SuperH_DivCalls),
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
index 6ea386dbc1825..d38f602e504fe 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.cpp
@@ -24,7 +24,6 @@ SuperHMCAsmInfo::SuperHMCAsmInfo(const Triple &TheTriple,
   this->IsLittleEndian = TheTriple.isLittleEndian();
   this->CommentString = "!";
   this->InternalSymbolPrefix = ".L";
-  this->PrivateLabelPrefix = ".L";
   this->MinInstAlignment = 1;
 
   // NOTE:  GAS SH Assembly uses Log2(N) alignment specifiers,
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 7ef5be9305863..d275c40055e5b 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -344,7 +344,7 @@ bool SuperHFrameLowering::canSimplifyCallFramePseudos(
 
 bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
+  return MF.disableFramePointerElim() ||
          MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index d378a6878e196..3035002d92e85 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -137,6 +137,7 @@ static bool RetCC_SH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
   return true;
 }
 
+#define GET_CALLING_CONV_IMPL
 #include "SuperHGenCallingConv.inc"
 
 
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
index 4967df1a71c97..93c86db7c50c5 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
@@ -25,10 +25,10 @@ using namespace llvm;
 #define GET_SUBTARGETINFO_CTOR
 #include "SuperHGenSubtargetInfo.inc"
 
-SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU, 
-                                 const StringRef &FS,  const TargetMachine &TM)
-    : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, TuneCPU, FS), TM(TM),
-      InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)), 
+SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &FS,
+                                 const TargetMachine &TM)
+    : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, CPU, FS), TM(TM),
+      InstrInfo(initializeSubtargetDependencies(CPU, FS)), 
       TLInfo(TM, *this), TSInfo(), FrameLowering(*this) {
 }
 
@@ -36,15 +36,13 @@ SuperHSubtarget::~SuperHSubtarget() = default;
 
 
 SuperHSubtarget &SuperHSubtarget::initializeSubtargetDependencies(
-    StringRef CPU, StringRef TuneCPU, StringRef FS) {
-  const Triple &TT = getTargetTriple();
+    StringRef CPU, StringRef FS) {
   // Determine default and user specified characteristics
+  const Triple &TT = getTargetTriple();
   std::string CPUName = std::string(CPU);
-  if (TuneCPU.empty())
-    TuneCPU = CPUName;
 
   // Parse features string.
-  ParseSubtargetFeatures(CPUName, TuneCPU, FS);
+  ParseSubtargetFeatures(CPUName, CPUName, FS);
   return *this;
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.h b/llvm/lib/Target/SuperH/SuperHSubtarget.h
index a6aa38aaf98c8..55c4a0a1ee9ff 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.h
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.h
@@ -55,8 +55,8 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
 #include "SuperHGenSubtargetInfo.inc"
 
 public:
-  SuperHSubtarget(const StringRef &CPU, const StringRef &TuneCPU, 
-                  const StringRef &FS,  const TargetMachine &TM);
+  SuperHSubtarget(const StringRef &CPU, const StringRef &FS, 
+                  const TargetMachine &TM);
 
   ~SuperHSubtarget() override;
 
@@ -101,7 +101,6 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
   /// 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);
 };
 
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 4dcced86224f3..ecfb8616580ec 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -105,20 +105,15 @@ TargetPassConfig *SuperHTargetMachine::createPassConfig(PassManagerBase &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);
-  }
+  if (!ST)
+    ST = std::make_unique<SuperHSubtarget>(CPU, FS, *this);
   return ST.get();
 }
 

>From 6e75f82bedf50aa110f0ddcacf8ff0cf7b8ef44b Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Wed, 16 Sep 2026 21:01:00 +0200
Subject: [PATCH 51/67] clang-format

---
 clang/lib/Basic/Targets/SuperH.cpp            |  16 +-
 clang/lib/Basic/Targets/SuperH.h              |   9 +-
 clang/lib/CodeGen/CodeGenModule.cpp           |   2 +-
 clang/lib/CodeGen/Targets/SuperH.cpp          |  12 +-
 llvm/include/llvm/TargetParser/Triple.h       |   2 +-
 .../SuperH/AsmParser/SuperHAsmParser.cpp      | 222 +++++----
 .../SuperH/MCTargetDesc/SuperHAsmBackend.cpp  |  83 ++--
 .../SuperH/MCTargetDesc/SuperHAsmBackend.h    |  15 +-
 .../MCTargetDesc/SuperHELFObjectWriter.cpp    |  39 +-
 .../SuperH/MCTargetDesc/SuperHInstPrinter.cpp |  64 ++-
 .../SuperH/MCTargetDesc/SuperHInstPrinter.h   |  11 +-
 .../SuperH/MCTargetDesc/SuperHMCAsmInfo.h     |   5 +-
 .../MCTargetDesc/SuperHMCCodeEmitter.cpp      | 124 ++---
 .../MCTargetDesc/SuperHMCTargetDesc.cpp       |   5 +-
 .../SuperH/MCTargetDesc/SuperHMCTargetDesc.h  |  14 +-
 .../MCTargetDesc/SuperHTargetStreamer.cpp     |   5 +-
 llvm/lib/Target/SuperH/SuperH.h               |   4 +-
 llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp   |  57 ++-
 .../Target/SuperH/SuperHBasicBlockInfo.cpp    |  26 +-
 llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h |   3 +-
 .../SuperH/SuperHConstantIslandPass.cpp       | 430 +++++++++---------
 .../Target/SuperH/SuperHConstantPoolValue.cpp | 106 +++--
 .../Target/SuperH/SuperHConstantPoolValue.h   | 100 ++--
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 233 +++++-----
 .../Target/SuperH/SuperHFillDelaySlots.cpp    |  36 +-
 .../lib/Target/SuperH/SuperHFrameLowering.cpp | 163 ++++---
 llvm/lib/Target/SuperH/SuperHFrameLowering.h  |  31 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 103 ++---
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 152 ++++---
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |  73 +--
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 141 +++---
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |  21 +-
 llvm/lib/Target/SuperH/SuperHMCInstLower.cpp  |   6 +-
 .../SuperH/SuperHMachineFunctionInfo.cpp      |  77 ++--
 .../Target/SuperH/SuperHMachineFunctionInfo.h |  30 +-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp |  63 +--
 llvm/lib/Target/SuperH/SuperHRegisterInfo.h   |  16 +-
 llvm/lib/Target/SuperH/SuperHSubtarget.cpp    |  59 +--
 llvm/lib/Target/SuperH/SuperHSubtarget.h      |  24 +-
 .../lib/Target/SuperH/SuperHTargetMachine.cpp |  18 +-
 llvm/lib/Target/SuperH/SuperHTargetMachine.h  |   9 +-
 .../SuperH/TargetInfo/SuperHTargetInfo.cpp    |  12 +-
 42 files changed, 1330 insertions(+), 1291 deletions(-)

diff --git a/clang/lib/Basic/Targets/SuperH.cpp b/clang/lib/Basic/Targets/SuperH.cpp
index 62387f6515cfe..e259faa3b3a2a 100644
--- a/clang/lib/Basic/Targets/SuperH.cpp
+++ b/clang/lib/Basic/Targets/SuperH.cpp
@@ -22,20 +22,16 @@ struct LLVM_LIBRARY_VISIBILITY SHCPUInfo {
 };
 
 static constexpr SHCPUInfo CPUInfo[] = {
-  {{"sh1"}},
-  {{"sh2"}},
-  {{"sh2a"}},
-  {{"sh3"}},
-  {{"sh4"}},
-  {{"sh4a"}},
+    {{"sh1"}}, {{"sh2"}}, {{"sh2a"}}, {{"sh3"}}, {{"sh4"}}, {{"sh4a"}},
 };
 
 bool SuperHTargetInfo::isValidCPUName(StringRef Name) const {
-  return llvm::any_of(
-      CPUInfo, [&](const SHCPUInfo &Info) { return Info.Name == Name; });
+  return llvm::any_of(CPUInfo,
+                      [&](const SHCPUInfo &Info) { return Info.Name == Name; });
 }
 
-void SuperHTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
+void SuperHTargetInfo::fillValidCPUList(
+    SmallVectorImpl<StringRef> &Values) const {
   for (const SHCPUInfo &Info : CPUInfo)
     Values.push_back(Info.Name);
 }
@@ -60,7 +56,7 @@ SuperHTargetInfo::handleAsmEscapedChar(char EscChar) const {
 }
 
 void SuperHTargetInfo::getTargetDefines(const LangOptions &Opts,
-                                     MacroBuilder &Builder) const {
+                                        MacroBuilder &Builder) const {
   Builder.defineMacro("SH");
   Builder.defineMacro("__SH");
   Builder.defineMacro("__SH__");
diff --git a/clang/lib/Basic/Targets/SuperH.h b/clang/lib/Basic/Targets/SuperH.h
index 974ea928e47e3..11d51e9d69880 100644
--- a/clang/lib/Basic/Targets/SuperH.h
+++ b/clang/lib/Basic/Targets/SuperH.h
@@ -77,9 +77,8 @@ class LLVM_LIBRARY_VISIBILITY SuperHTargetInfo : public TargetInfo {
 
   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"
-    };
+        "r0", "r1", "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
+        "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"};
     return llvm::ArrayRef(GCCRegNames);
   }
 
@@ -107,7 +106,7 @@ class LLVM_LIBRARY_VISIBILITY SuperHTargetInfo : public TargetInfo {
   StringRef ABI;
 };
 
-}
-}
+} // namespace targets
+} // namespace clang
 
 #endif
\ No newline at end of file
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index f0b95456ca025..5e4577eb0f5fb 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -246,7 +246,7 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
     bool EABI = ABIStr.ends_with("e");
     return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
   }
-  
+
   case llvm::Triple::sh:
   case llvm::Triple::shl: {
     return createSuperHTargetCodeGenInfo(CGM);
diff --git a/clang/lib/CodeGen/Targets/SuperH.cpp b/clang/lib/CodeGen/Targets/SuperH.cpp
index eae3cd39de190..3b2a15faa7d5a 100644
--- a/clang/lib/CodeGen/Targets/SuperH.cpp
+++ b/clang/lib/CodeGen/Targets/SuperH.cpp
@@ -22,15 +22,13 @@ using namespace clang::CodeGen;
 namespace {
 class SuperHABIInfo : public DefaultABIInfo {
 public:
-  SuperHABIInfo(CodeGenTypes &CGT)
-      : DefaultABIInfo(CGT) {}
+  SuperHABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
 
   ABIArgInfo classifyReturnType(QualType Ty, bool &LargeRet) const {
 
     // We have a total of 64 bits of return space in R0 and R1,
     // if we can fit a struct in there, do.
-    if (isAggregateTypeForABI(Ty) && 
-        getContext().getTypeSize(Ty) <= 64)
+    if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) <= 64)
       return ABIArgInfo::getDirect();
 
     // Otherwise, we store a pointer to the struct in R2 and return that.
@@ -70,22 +68,20 @@ class SuperHABIInfo : public DefaultABIInfo {
     bool LargeRet = false;
     if (!getCXXABI().classifyReturnType(FI))
       FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), LargeRet);
-    
+
     // Decide each argument type.
     unsigned NumRegs = 4;
     for (auto &I : FI.arguments())
       I.info = classifyArgumentType(I.type, NumRegs);
   }
-
 };
 
 class SuperHTargetCodeGenInfo : public TargetCodeGenInfo {
 public:
   SuperHTargetCodeGenInfo(CodeGenTypes &CGT)
       : TargetCodeGenInfo(std::make_unique<SuperHABIInfo>(CGT)) {}
-
 };
-}
+} // namespace
 
 std::unique_ptr<TargetCodeGenInfo>
 CodeGen::createSuperHTargetCodeGenInfo(CodeGenModule &CGM) {
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 475137cb38579..edf2532068c72 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -1193,7 +1193,7 @@ class Triple {
   bool isSPARC() const { return isSPARC32() || isSPARC64(); }
 
   /// Tests whether the target is SuperH.
-  bool isSuperH() const { 
+  bool isSuperH() const {
     return getArch() == Triple::sh || getArch() == Triple::shl;
   }
 
diff --git a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
index e4921dbac6cb5..8b9a0cce8551b 100644
--- a/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
+++ b/llvm/lib/Target/SuperH/AsmParser/SuperHAsmParser.cpp
@@ -10,37 +10,34 @@
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperHRegisterInfo.h"
 #include "TargetInfo/SuperHTargetInfo.h"
+#include "iostream"
 #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/MCValue.h"
-#include "llvm/MC/TargetRegistry.h"
 #include "llvm/MC/MCAsmMacro.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCELFStreamer.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrAnalysis.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/MCRegister.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugLog.h"
 #include "llvm/Support/LogicalResult.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>
@@ -54,7 +51,7 @@ using namespace llvm;
 namespace llvm {
 namespace SuperH {
 
-    using namespace SH;
+using namespace SH;
 
 } // end namespace SuperH
 } // end namespace llvm
@@ -64,7 +61,7 @@ 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());
+  ptrdiff_t Length = (ptrdiff_t)(EndLoc.getPointer() - StartLoc.getPointer());
   return StringRef(StartLoc.getPointer(), Length);
 }
 
@@ -75,24 +72,30 @@ class SuperHAsmParser : public MCTargetAsmParser {
 #define GET_ASSEMBLER_HEADER
 #include "SuperHGenAsmMatcher.inc"
 
-  bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override;
+  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;
+                               OperandVector &Operands, MCStreamer &Out,
+                               uint64_t &ErrorInfo,
+                               bool MatchingInlineAsm) override;
 
   // Register Parsing
-  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
+                               SMLoc &EndLoc) override;
   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
 
   // Parser helpers.
   MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
   ParseStatus tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc);
-  ParseStatus tryParseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc);
-  ParseStatus tryParseRegRelative(MCRegister &BaseReg, MCRegister &OffReg, const MCExpr *&Offset, SMLoc &StartLoc, SMLoc &EndLoc);
-  ParseStatus tryParseRegIndirect(MCRegister &Reg, bool &IsInc, bool &IsDec, SMLoc &StartLoc, SMLoc &EndLoc);
+  ParseStatus tryParseRegister(MCRegister &Reg, unsigned &RegKind,
+                               SMLoc &StartLoc, SMLoc &EndLoc);
+  ParseStatus tryParseRegRelative(MCRegister &BaseReg, MCRegister &OffReg,
+                                  const MCExpr *&Offset, SMLoc &StartLoc,
+                                  SMLoc &EndLoc);
+  ParseStatus tryParseRegIndirect(MCRegister &Reg, bool &IsInc, bool &IsDec,
+                                  SMLoc &StartLoc, SMLoc &EndLoc);
 
   // Parser entry points
   ParseStatus parseOperand(OperandVector &Operands);
@@ -103,8 +106,9 @@ class SuperHAsmParser : public MCTargetAsmParser {
   ParseStatus parseDisp(OperandVector &Operands);
 
 public:
-  SuperHAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII) 
-    : MCTargetAsmParser(sti, MII), Parser(parser),
+  SuperHAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
+                  const MCInstrInfo &MII)
+      : MCTargetAsmParser(sti, MII), Parser(parser),
         MRI(*Parser.getContext().getRegisterInfo()) {
 
     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
@@ -129,19 +133,18 @@ 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             = 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
+    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;
@@ -189,11 +192,16 @@ class SuperHOperand : public MCParsedAsmOperand {
   bool isImm() const override { return Kind == k_Immediate; }
   bool isReg() const override { return Kind == k_Register; }
   bool isDisp() const { return Kind == k_Displacement; }
-  bool isMem() const override { return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec | k_IndirectIndex)) != 0; }
+  bool isMem() const override {
+    return (Kind & (k_IndirectReg | k_IndirectRegInc | k_IndirectRegDec |
+                    k_IndirectIndex)) != 0;
+  }
   bool isIReg() const { return Kind == k_IndirectReg; }
   bool isIRegInc() const { return Kind == k_IndirectRegInc; }
   bool isIRegDec() const { return Kind == k_IndirectRegDec; }
-  bool isAnyReg() const { return isReg() || isIReg() || isIRegInc() || isIRegDec(); }
+  bool isAnyReg() const {
+    return isReg() || isIReg() || isIRegInc() || isIRegDec();
+  }
   bool isPCRel() const { return Kind == k_Displacement && Mem.Base == SH::PC; }
 
   SMLoc getStartLoc() const override { return StartLoc; }
@@ -232,7 +240,7 @@ class SuperHOperand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createReg(getReg()));
   }
 
-  void addExpr(MCInst &Inst, const MCExpr *Expr) const{
+  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
     // Add as immediate when possible.  Null MCExpr = 0.
     if (!Expr)
       Inst.addOperand(MCOperand::createImm(0));
@@ -286,7 +294,8 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
+  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;
@@ -294,7 +303,8 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateDisp(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {
+  static std::unique_ptr<SuperHOperand>
+  CreateDisp(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {
     auto Op = std::make_unique<SuperHOperand>(k_Displacement);
     Op->Mem.Base = Reg;
     Op->Mem.Offset = Val;
@@ -303,7 +313,8 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateSymRef(const MCExpr *Val, SMLoc S, SMLoc E) {
+  static std::unique_ptr<SuperHOperand> CreateSymRef(const MCExpr *Val, SMLoc S,
+                                                     SMLoc E) {
     auto Op = std::make_unique<SuperHOperand>(k_Displacement);
     Op->Mem.Base = SH::PC;
     Op->Mem.Offset = Val;
@@ -312,7 +323,8 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateIReg(MCRegister Reg, SMLoc S, SMLoc E) {
+  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;
@@ -320,7 +332,8 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateIRegInc(MCRegister Reg, SMLoc S, SMLoc E) {
+  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;
@@ -328,7 +341,8 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateIRegDec(MCRegister Reg, SMLoc S, SMLoc E) {
+  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;
@@ -336,8 +350,9 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateIIndex(MCRegister Base, MCRegister OffsetReg, 
-                                                     const MCExpr *Offset, 
+  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;
@@ -348,8 +363,8 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateExpr(const MCExpr *Expr, 
-                                                   SMLoc S, SMLoc E) {
+  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;
@@ -357,8 +372,8 @@ class SuperHOperand : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<SuperHOperand> CreateFromExpr(const MCExpr *Expr, 
-                                                   SMLoc S, SMLoc E) {
+  static std::unique_ptr<SuperHOperand> CreateFromExpr(const MCExpr *Expr,
+                                                       SMLoc S, SMLoc E) {
     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
       return CreateDisp(SH::PC, CE, S, E);
 
@@ -380,7 +395,7 @@ class SuperHOperand : public MCParsedAsmOperand {
     // Indirect register has @ prefix.
     if (isIReg())
       OS << "@";
-    
+
     // Pre-decrement.
     if (isIRegDec())
       OS << "-";
@@ -402,39 +417,40 @@ class SuperHOperand : public MCParsedAsmOperand {
 #define GET_MNEMONIC_CHECKER
 #include "SuperHGenAsmMatcher.inc"
 
-MCRegister SuperHAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegKind) {
+MCRegister SuperHAsmParser::matchRegisterName(const AsmToken &Tok,
+                                              unsigned &RegKind) {
   RegKind = SuperHOperand::rk_None;
-  if(Tok.isNot(AsmToken::Identifier))
+  if (Tok.isNot(AsmToken::Identifier))
     return SH::NoRegister;
 
   std::string Name = Tok.getString().lower();
   MCRegister Reg = MatchRegisterName(Name);
   if (MRI.getRegClass(SH::GPRRegClassID).contains(Reg)) {
-    
+
     // General purpose register class.
     RegKind = SuperHOperand::rk_GPR;
   } else if (Reg == SH::XMTRX) {
-    
+
     // XMTRX register.
     RegKind = SuperHOperand::rk_XMTRX;
   } else if (MRI.getRegClass(SH::SYSRegClassID).contains(Reg)) {
-    
+
     // System register class.
     RegKind = SuperHOperand::rk_SYS;
   } else if (MRI.getRegClass(SH::CTRLRegClassID).contains(Reg)) {
-    
+
     // Control register class.
     RegKind = SuperHOperand::rk_CTRL;
   } else if (MRI.getRegClass(SH::FR32RegClassID).contains(Reg)) {
-    
+
     // 32-bit float registers.
     RegKind = SuperHOperand::rk_FR32;
   } else if (MRI.getRegClass(SH::FR64RegClassID).contains(Reg)) {
-    
+
     // 64-bit float registers.
     RegKind = SuperHOperand::rk_FR64;
   } else if (MRI.getRegClass(SH::VEC128RegClassID).contains(Reg)) {
-    
+
     // 128-bit vector registers.
     RegKind = SuperHOperand::rk_VEC128;
   }
@@ -442,13 +458,15 @@ MCRegister SuperHAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &Reg
   return Reg;
 }
 
-bool SuperHAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) {
+bool SuperHAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
+                                    SMLoc &EndLoc) {
   if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
-      return Error(StartLoc, "invalid register name");
+    return Error(StartLoc, "invalid register name");
   return false;
 }
 
-ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) {
+ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
+                                              SMLoc &EndLoc) {
   unsigned RegKind;
   const AsmToken Tok = Parser.getTok();
   StartLoc = Tok.getLoc();
@@ -472,7 +490,9 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
 //===----------------------------------------------------------------------===//
 
 // Try parsing a register by its name.
-ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, unsigned &RegKind, SMLoc &StartLoc, SMLoc &EndLoc) {
+ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg,
+                                              unsigned &RegKind,
+                                              SMLoc &StartLoc, SMLoc &EndLoc) {
   const AsmToken Tok = Parser.getTok();
   StartLoc = Tok.getLoc();
   EndLoc = Tok.getEndLoc();
@@ -488,8 +508,10 @@ ParseStatus SuperHAsmParser::tryParseRegister(MCRegister &Reg, unsigned &RegKind
 }
 
 // Parses register relative addressing modes.
-ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister &OffReg, 
-                                                 const MCExpr *&Offset, SMLoc &StartLoc, 
+ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg,
+                                                 MCRegister &OffReg,
+                                                 const MCExpr *&Offset,
+                                                 SMLoc &StartLoc,
                                                  SMLoc &EndLoc) {
   const AsmToken Tok = getTok();
   unsigned RegKind;
@@ -497,11 +519,12 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
   // NOTE:  SuperH Assemblers support subtituting the normal PC-relative form
   //        with a symbol reference.
   //
-  //        The following instruction sequences are equivalent:        
-  //          mova .ABC, r0  
+  //        The following instruction sequences are equivalent:
+  //          mova .ABC, r0
   //          mova @(.ABC,pc), r0
   //          mova @(8,pc), r0      (Where 8 is an offset from PC that refers
-  //                                 to the same address as the identifier would)
+  //                                 to the same address as the identifier
+  //                                 would)
   if (getTok().is(AsmToken::Identifier)) {
 
     // Registers are *not* identifiers.
@@ -517,7 +540,8 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
   }
 
   // Parse "@(" sequence
-  if (getTok().isNot(AsmToken::At) || getLexer().peekTok().isNot(AsmToken::LParen)) {
+  if (getTok().isNot(AsmToken::At) ||
+      getLexer().peekTok().isNot(AsmToken::LParen)) {
     return ParseStatus::NoMatch;
   }
   Parser.Lex();
@@ -544,7 +568,8 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
     Offset = MCConstantExpr::create(Disp, getContext());
   } else {
 
-    return Error(getTok().getLoc(), "expected identifier, register or displacement");
+    return Error(getTok().getLoc(),
+                 "expected identifier, register or displacement");
   }
 
   // Parse seperator
@@ -564,12 +589,13 @@ ParseStatus SuperHAsmParser::tryParseRegRelative(MCRegister &BaseReg, MCRegister
 }
 
 // Parses register-indirect addressing in the following forms:
-// 
+//
 //   @Rn  - Register Indirect
 //   @-Rn - Register Indirect with Pre-decrement
 //   @Rn+ - Register Indirect with Post-increment
-ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, bool &IsDec, 
-                                                 SMLoc &StartLoc, SMLoc &EndLoc) {
+ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc,
+                                                 bool &IsDec, SMLoc &StartLoc,
+                                                 SMLoc &EndLoc) {
   const AsmToken Tok = Parser.getTok();
   SMLoc S = StartLoc;
   SMLoc E = EndLoc;
@@ -601,7 +627,8 @@ ParseStatus SuperHAsmParser::tryParseRegIndirect(MCRegister &Reg, bool &IsInc, b
   return ParseStatus::Success;
 }
 
-ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc, SMLoc &EndLoc) {
+ParseStatus SuperHAsmParser::tryParseImm(int64_t &Imm, SMLoc &StartLoc,
+                                         SMLoc &EndLoc) {
   const AsmToken Tok = Parser.getTok();
 
   // Eat % and $ which are used in SuperH asm.
@@ -632,14 +659,11 @@ ParseStatus SuperHAsmParser::parseImm(OperandVector &Operands) {
   // Immediates start with a '#'
   if (!Parser.parseOptionalToken(AsmToken::Hash))
     return ParseStatus::NoMatch;
-  
+
   int64_t Imm;
   if (tryParseImm(Imm, StartLoc, EndLoc).isSuccess()) {
     Operands.push_back(SuperHOperand::CreateImm(
-      MCConstantExpr::create(Imm, getContext()), 
-      StartLoc, 
-      EndLoc
-    ));
+        MCConstantExpr::create(Imm, getContext()), StartLoc, EndLoc));
     return ParseStatus::Success;
   }
 
@@ -657,12 +681,13 @@ ParseStatus SuperHAsmParser::parsePCRel(OperandVector &Operands) {
   const AsmToken Tok = Parser.getTok();
   SMLoc StartLoc = getLexer().getLoc();
   SMLoc EndLoc = getLexer().getLoc();
-  
+
   // Parse register relative.
   MCRegister BaseReg;
   MCRegister OffReg;
   const MCExpr *Offset;
-  ParseStatus Result = tryParseRegRelative(BaseReg, OffReg, Offset, StartLoc, EndLoc);
+  ParseStatus Result =
+      tryParseRegRelative(BaseReg, OffReg, Offset, StartLoc, EndLoc);
   if (!Result.isSuccess())
     return Result;
 
@@ -685,7 +710,8 @@ ParseStatus SuperHAsmParser::parseRegister(OperandVector &Operands) {
   MCRegister Reg;
   unsigned RegKind;
   if (tryParseRegister(Reg, RegKind, StartLoc, EndLoc).isSuccess()) {
-    Operands.push_back(SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
+    Operands.push_back(
+        SuperHOperand::CreateReg(Reg, RegKind, StartLoc, EndLoc));
     return ParseStatus::Success;
   }
   return ParseStatus::NoMatch;
@@ -739,10 +765,10 @@ ParseStatus SuperHAsmParser::parseDirective(AsmToken DirectiveID) {
       return ParseStatus::Success;
   }
   if (IDVal.equals_insensitive(".little")) {
-      return ParseStatus::Success;
+    return ParseStatus::Success;
   }
   if (IDVal.equals_insensitive(".big")) {
-      return ParseStatus::Success;
+    return ParseStatus::Success;
   }
   return ParseStatus::NoMatch;
 }
@@ -757,14 +783,16 @@ ParseStatus SuperHAsmParser::parseOperand(OperandVector &Operands) {
   }
 }
 
-bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Mnemonic, 
-                                       SMLoc NameLoc, OperandVector &Operands) {
+bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info,
+                                       StringRef Mnemonic, SMLoc NameLoc,
+                                       OperandVector &Operands) {
 
   // Match mnemonic.
   bool MS = SuperHCheckMnemonic(Mnemonic, this->getAvailableFeatures(), 0);
   if (!MS) {
-    return Error(NameLoc, "invalid instruction mnemonic" + 
-      SuperHMnemonicSpellCheck(Mnemonic, getAvailableFeatures(), 0));
+    return Error(NameLoc, "invalid instruction mnemonic" +
+                              SuperHMnemonicSpellCheck(
+                                  Mnemonic, getAvailableFeatures(), 0));
   }
 
   // Chomp name and add it to the operands.
@@ -789,7 +817,7 @@ bool SuperHAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Mne
       Parser.eatToEndOfStatement();
       return true;
     }
-    
+
     // Initial operand
     if (!parseOperand(Operands).isSuccess()) {
       SMLoc Loc = getLexer().getLoc();
@@ -815,20 +843,23 @@ bool SuperHAsmParser::parseGNUAttribute(SMLoc L) {
 }
 
 bool SuperHAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
-                                     OperandVector &Operands, MCStreamer &Out,
-                                     uint64_t &ErrorInfo,
-                                     bool MatchingInlineAsm) {
-  
+                                              OperandVector &Operands,
+                                              MCStreamer &Out,
+                                              uint64_t &ErrorInfo,
+                                              bool MatchingInlineAsm) {
+
   LLVM_DEBUG(dbgs() << "matchAndEmitInstruction\n");
   MCInst Inst;
-  unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
-  switch(MatchResult) {
+  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.");
+    return Error(IDLoc,
+                 "instruction requires a CPU feature not currently enabled.");
   case Match_InvalidOperand: {
     SMLoc ErrorLoc = IDLoc;
     if (ErrorInfo != ~0ULL) {
@@ -848,7 +879,6 @@ bool SuperHAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   return false;
 }
 
-
 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
 LLVMInitializeSuperHAsmParser() {
   RegisterMCAsmParser<SuperHAsmParser> A(getTheSuperHTarget());
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index 5adcf90b23458..e03896936980e 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -34,15 +34,14 @@
 
 using namespace llvm;
 
-SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) : 
-                  MCAsmBackend(STI.getTargetTriple().isLittleEndian()
-                         ? llvm::endianness::little
-                         : llvm::endianness::big),
-                  STI(STI), OSABI(OSABI) {
-}
+SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI)
+    : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
+                       ? llvm::endianness::little
+                       : llvm::endianness::big),
+      STI(STI), OSABI(OSABI) {}
 
 bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
-                    const MCSubtargetInfo *STI) const {
+                                    const MCSubtargetInfo *STI) const {
   const uint16_t SHNopEnc = 0b0000000000001001;
 
   // If the count is not 4-byte aligned, we must be writing data into the
@@ -56,7 +55,8 @@ bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
   OS.write_zeros(Count & 1);
   return true;
 }
-std::optional<MCFixupKind> SuperHAsmBackend::getFixupKind(StringRef Name) const {
+std::optional<MCFixupKind>
+SuperHAsmBackend::getFixupKind(StringRef Name) const {
   if (STI.getTargetTriple().isOSBinFormatELF()) {
     unsigned Type;
     Type = llvm::StringSwitch<unsigned>(Name)
@@ -99,9 +99,11 @@ MCFixupKindInfo SuperHAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
   return Infos[Kind - FirstTargetFixupKind];
 }
 
-unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
-                                            const MCValue &Target, uint64_t Value,
-                                            bool IsResolved, MCContext &Ctx,
+unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm,
+                                            const MCFixup &Fixup,
+                                            const MCValue &Target,
+                                            uint64_t Value, bool IsResolved,
+                                            MCContext &Ctx,
                                             const MCSubtargetInfo *STI) const {
   unsigned Kind = Fixup.getKind();
   int64_t Addend = Target.getConstant();
@@ -111,31 +113,31 @@ unsigned SuperHAsmBackend::adjustFixupValue(const MCAssembler &Asm, const MCFixu
     return Value;
 
   case SH::fixup_32:
-    return (Value+Addend) & 0xFFFFFFFF;
+    return (Value + Addend) & 0xFFFFFFFF;
 
   case SH::fixup_pcrel4_by2:
-    return ((Value+Addend) / 2) & 0xF;
+    return ((Value + Addend) / 2) & 0xF;
 
   case SH::fixup_pcrel4_by4:
-    return ((Value+Addend) / 4) & 0xF;
-  
+    return ((Value + Addend) / 4) & 0xF;
+
   case SH::fixup_pcrel8_by4:
-    return ((Value+Addend) / 4) & 0xFF;
-  
+    return ((Value + Addend) / 4) & 0xFF;
+
   case SH::fixup_pcrel8_4by2:
     return ((alignTo(Value, 2) + Addend - 4) / 2) & 0xFF;
-  
+
   case SH::fixup_pcrel8_4by4:
     return ((alignTo(Value, 4) + Addend - 4) / 4) & 0xFF;
-  
+
   case SH::fixup_pcrel12_4by2:
     return ((alignTo(Value, 2) + Addend - 4) / 2) & 0xFFF;
   }
 }
 
 bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
-                               const MCValue &Target, uint64_t &FixedValue,
-                               bool IsResolved) {
+                                   const MCValue &Target, uint64_t &FixedValue,
+                                   bool IsResolved) {
   if (!IsResolved) {
     Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
     return false;
@@ -143,19 +145,21 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
   return true;
 }
 
-std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup &Fixup,
-                                                    MCValue &Target, uint64_t &FixedValue) {
+std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F,
+                                                    MCFixup &Fixup,
+                                                    MCValue &Target,
+                                                    uint64_t &FixedValue) {
   MCValue PCITarget; // PC-Indirect Target
 
   // Get indirect target location.
-  switch(Fixup.getKind()) {
-  default: 
+  switch (Fixup.getKind()) {
+  default:
     return {};
 
   case FK_Data_1:
   case FK_Data_2:
   case FK_Data_4:
-  case FK_Data_8: 
+  case FK_Data_8:
   case SH::fixup_pcrel4_by2:
   case SH::fixup_pcrel4_by4:
   case SH::fixup_pcrel8_by4:
@@ -180,8 +184,8 @@ std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup
 
   // Check if resolvable.
   bool IsResolved = &SA.getSection() == F.getParent() &&
-                     SA.getBinding() == ELF::STB_LOCAL &&
-                     SA.getType() != ELF::STT_GNU_IFUNC;
+                    SA.getBinding() == ELF::STB_LOCAL &&
+                    SA.getType() != ELF::STT_GNU_IFUNC;
   if (!IsResolved)
     return false;
 
@@ -194,20 +198,20 @@ std::optional<bool> SuperHAsmBackend::evaluateFixup(const MCFragment &F, MCFixup
 }
 
 void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
-                                 const MCValue &Target, uint8_t *Data,
-                                 uint64_t Value, bool IsResolved) {
-  
+                                  const MCValue &Target, uint8_t *Data,
+                                  uint64_t Value, bool IsResolved) {
+
   // Handle Relocations
   IsResolved = tryAddReloc(F, Fixup, Target, Value, IsResolved);
   MCFixupKind Kind = Fixup.getKind();
-  if (mc::isRelocation(Kind)) 
+  if (mc::isRelocation(Kind))
     return;
 
   // Handle non-relocations
   MCContext &Ctx = getContext();
   MCFixupKindInfo Info = getFixupKindInfo(Kind);
-  Value = adjustFixupValue(*Asm, Fixup, Target, Value, IsResolved, 
-                           Ctx, getSubtargetInfo(F));
+  Value = adjustFixupValue(*Asm, Fixup, Target, Value, IsResolved, Ctx,
+                           getSubtargetInfo(F));
 
   if (!Value)
     return; // No encoding change.
@@ -226,15 +230,16 @@ void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
   }
 }
 
-std::unique_ptr<MCObjectTargetWriter> 
+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) {
-  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS());
+                                           const MCSubtargetInfo &STI,
+                                           const MCRegisterInfo &MRI,
+                                           const MCTargetOptions &Options) {
+  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
index 833e1247b152a..27e4259347d81 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
@@ -9,13 +9,12 @@
 #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 "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 
-
 namespace llvm {
 class MCAssembler;
 class MCObjectTargetWriter;
@@ -25,6 +24,7 @@ class SuperHAsmBackend : public MCAsmBackend {
 protected:
   const MCSubtargetInfo &STI;
   uint8_t OSABI;
+
 public:
   SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI);
   ~SuperHAsmBackend() override = default;
@@ -36,17 +36,16 @@ class SuperHAsmBackend : public MCAsmBackend {
                   uint8_t *Data, uint64_t Value, bool IsResolved) override;
   std::optional<bool> evaluateFixup(const MCFragment &, MCFixup &, MCValue &,
                                     uint64_t &) override;
-	
-	std::unique_ptr<MCObjectTargetWriter>
+
+  std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override;
-  
+
   bool writeNopData(raw_ostream &OS, uint64_t Count,
                     const MCSubtargetInfo *STI) const override;
-  
 
   bool tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
-                               const MCValue &Target, uint64_t &FixedValue,
-                               bool IsResolved);
+                   const MCValue &Target, uint64_t &FixedValue,
+                   bool IsResolved);
 
   unsigned adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
                             const MCValue &Target, uint64_t Value,
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
index b7910e8bb2315..1120c2af87e0b 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHELFObjectWriter.cpp
@@ -6,9 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "MCTargetDesc/SuperHBaseInfo.h"
 #include "MCTargetDesc/SuperHFixupKinds.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperHMCAsmInfo.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/MCContext.h"
@@ -25,29 +25,28 @@ using namespace llvm;
 #define DEBUG_TYPE "sh-elf-objwriter"
 
 namespace llvm {
-  class SuperHELFObjectWriter : public MCELFObjectTargetWriter {
-  public:
-    SuperHELFObjectWriter(uint8_t OSABI)
-        : MCELFObjectTargetWriter(
-              false, OSABI,
-              ELF::EM_SH,
-              /*HasRelocationAddend*/ true) {}
+class SuperHELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+  SuperHELFObjectWriter(uint8_t OSABI)
+      : MCELFObjectTargetWriter(false, OSABI, ELF::EM_SH,
+                                /*HasRelocationAddend*/ true) {}
 
-    ~SuperHELFObjectWriter() override = default;
+  ~SuperHELFObjectWriter() override = default;
 
-  protected:
-    unsigned getRelocType(const MCFixup &Fixup, const MCValue &Target,
-                          bool IsPCRel) const override;
+protected:
+  unsigned getRelocType(const MCFixup &Fixup, const MCValue &Target,
+                        bool IsPCRel) const override;
 
-    bool needsRelocateWithSymbol(const MCValue &Val, unsigned Type) const override;
-  };
-}
+  bool needsRelocateWithSymbol(const MCValue &Val,
+                               unsigned Type) const override;
+};
+} // namespace llvm
 
 unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
-                                            const MCValue &Target,
-                                            bool IsPCRel) const {
+                                             const MCValue &Target,
+                                             bool IsPCRel) const {
   auto Spec = Target.getSpecifier();
-  switch ((unsigned)Fixup.getKind()) { 
+  switch ((unsigned)Fixup.getKind()) {
   case FK_Data_1:
   case FK_Data_2:
   case FK_Data_8:
@@ -63,7 +62,7 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
       return ELF::R_SH_NONE;
     }
   }
-  
+
   case SH::fixup_pcrel4_by2:
   case SH::fixup_pcrel4_by4:
   case SH::fixup_pcrel8_by4:
@@ -88,7 +87,7 @@ unsigned SuperHELFObjectWriter::getRelocType(const MCFixup &Fixup,
 }
 
 bool SuperHELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
-                                                   unsigned Type) const {
+                                                    unsigned Type) const {
 
   return false;
 }
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
index 22b993ca7208a..00e437133869f 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.cpp
@@ -26,17 +26,19 @@ using namespace llvm;
 // The generated AsmMatcher SparcGenAsmWriter uses "SuperH" as the target
 // namespace. But SuperH backend uses "SH" as its namespace.
 namespace llvm {
-  namespace SuperH {
-    using namespace SH;
-  }
+namespace SuperH {
+using namespace SH;
 }
+} // namespace llvm
 
 #define GET_INSTRUCTION_NAME
 #define PRINT_ALIAS_INSTR
 #include "SuperHGenAsmWriter.inc"
 
-SuperHInstPrinter::SuperHInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
-                    const MCRegisterInfo &MRI) : MCInstPrinter(MAI, MII, MRI) {}
+SuperHInstPrinter::SuperHInstPrinter(const MCAsmInfo &MAI,
+                                     const MCInstrInfo &MII,
+                                     const MCRegisterInfo &MRI)
+    : MCInstPrinter(MAI, MII, MRI) {}
 
 const std::string SuperHInstPrinter::getRegName(MCRegister Reg) {
   return StringRef(getRegisterName(Reg)).lower();
@@ -46,40 +48,46 @@ void SuperHInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
   OS << getRegName(Reg);
 }
 
-void SuperHInstPrinter::printImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+void SuperHInstPrinter::printImm(const MCInst *MI, unsigned OpNo,
+                                 raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
   OS << "#" << Op.getImm();
 }
 
-void SuperHInstPrinter::printIReg(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+void SuperHInstPrinter::printIReg(const MCInst *MI, unsigned OpNo,
+                                  raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
   OS << "@" << getRegName(Op.getReg());
 }
 
-void SuperHInstPrinter::printIRegInc(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+void SuperHInstPrinter::printIRegInc(const MCInst *MI, unsigned OpNo,
+                                     raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
   OS << "@" << getRegName(Op.getReg()) << "+";
 }
 
-void SuperHInstPrinter::printIRegDec(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+void SuperHInstPrinter::printIRegDec(const MCInst *MI, unsigned OpNo,
+                                     raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
   OS << "@-" << getRegName(Op.getReg());
 }
 
-template<int Scale>
-void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+template <int Scale>
+void SuperHInstPrinter::printDisp(const MCInst *MI, unsigned OpNo,
+                                  raw_ostream &OS) {
   const MCOperand &Op = MI->getOperand(OpNo);
   OS << Op.getImm();
 }
 
-template<int Scale>
-void SuperHInstPrinter::printPCRel(const MCInst *MI, uint64_t Address, 
-                                      unsigned OpNo, raw_ostream &O) {
+template <int Scale>
+void SuperHInstPrinter::printPCRel(const MCInst *MI, uint64_t Address,
+                                   unsigned OpNo, raw_ostream &O) {
   const MCOperand &Op = MI->getOperand(OpNo);
 
   // Print standalone symbol.
   if (Op.isExpr()) {
-    if (const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op.getExpr())) {
+    if (const MCSymbolRefExpr *SymOp =
+            dyn_cast<MCSymbolRefExpr>(Op.getExpr())) {
       O << SymOp->getSymbol().getName();
       return;
     }
@@ -91,20 +99,22 @@ void SuperHInstPrinter::printPCRel(const MCInst *MI, uint64_t Address,
   }
 }
 
-template<int Scale>
-void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &OS) {
+template <int Scale>
+void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,
+                                   raw_ostream &OS) {
 
   // Skip "Uses" operands, as some Memri operations are destinations.
-  if (MI->getOperand(OpNo+1).isReg())
+  if (MI->getOperand(OpNo + 1).isReg())
     OpNo++;
 
   const MCOperand &Op0 = MI->getOperand(OpNo);
-  const MCOperand &Op1 = MI->getOperand(OpNo+1);
+  const MCOperand &Op1 = MI->getOperand(OpNo + 1);
 
   // For globals, we want to render a symbol.
   // even if they get lowered beforehand.
   if (Op0.isExpr()) {
-    if (const MCSymbolRefExpr *SymOp = dyn_cast<MCSymbolRefExpr>(Op0.getExpr())) {
+    if (const MCSymbolRefExpr *SymOp =
+            dyn_cast<MCSymbolRefExpr>(Op0.getExpr())) {
       OS << SymOp->getSymbol().getName();
       return;
     }
@@ -114,11 +124,13 @@ void SuperHInstPrinter::printMemri(const MCInst *MI, unsigned OpNo, raw_ostream
   OS << "@(" << Op1.getImm() << "," << getRegName(Op0.getReg()) << ")";
 }
 
-void SuperHInstPrinter::printMemrii(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
+void SuperHInstPrinter::printMemrii(const MCInst *MI, unsigned OpNo,
+                                    raw_ostream &O) {
   printOperand(MI, OpNo, O);
 }
 
-void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
+void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
+                                     raw_ostream &O) {
   const MCOperand &Op = MI->getOperand(OpNo);
 
   // Print Register
@@ -134,13 +146,15 @@ void SuperHInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostrea
   }
 
   // Print symbol references
-  if (const MCSymbolRefExpr *SymOp = dyn_cast_or_null<MCSymbolRefExpr>(Op.getExpr())) {
+  if (const MCSymbolRefExpr *SymOp =
+          dyn_cast_or_null<MCSymbolRefExpr>(Op.getExpr())) {
     O << SymOp->getSymbol().getName();
     return;
   }
 }
 
-void SuperHInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
-                 const MCSubtargetInfo &STI, raw_ostream &OS) {
+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 2a95c92f064c6..a4a27395edc4d 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHInstPrinter.h
@@ -50,13 +50,14 @@ class SuperHInstPrinter : public MCInstPrinter {
   static const char *getRegisterName(MCRegister Reg);
   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
 
-  template<int Scale>
-  void printPCRel(const MCInst *MI, uint64_t Address, unsigned OpNo, raw_ostream &O);
+  template <int Scale>
+  void printPCRel(const MCInst *MI, uint64_t Address, unsigned OpNo,
+                  raw_ostream &O);
 
-  template<int Scale>
+  template <int Scale>
   void printDisp(const MCInst *MI, unsigned OpNo, raw_ostream &O);
-  
-  template<int Scale>
+
+  template <int Scale>
   void printMemri(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printMemrii(const MCInst *MI, unsigned OpNo, raw_ostream &O);
   void printImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
index 232d952eb05f8..26a05673b368d 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCAsmInfo.h
@@ -11,7 +11,6 @@
 ///
 //===----------------------------------------------------------------------===//
 
-
 #ifndef LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCASMINFO_H
 #define LLVM_LIB_TARGET_SUPERH_MCTARGETDESC_SUPERHMCASMINFO_H
 
@@ -28,10 +27,10 @@ class Triple;
 //===----------------------------------------------------------------------===//
 class SuperHMCAsmInfo : public MCAsmInfoELF {
 private:
-	void anchor() override;
+  void anchor() override;
 
 public:
-	explicit SuperHMCAsmInfo(const Triple &TheTriple,
+  explicit SuperHMCAsmInfo(const Triple &TheTriple,
                            const MCTargetOptions &Options);
 };
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 848cff47c4ace..5c49947f963c3 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -10,7 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-
 #include "SuperHFixupKinds.h"
 #include "SuperHMCTargetDesc.h"
 #include "llvm/ADT/Statistic.h"
@@ -19,23 +18,22 @@
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/MC/TargetRegistry.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCFixup.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.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/MC/TargetRegistry.h"
 #include "llvm/Support/EndianStream.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <cstdint>
 #include <optional>
 
-
 using namespace llvm;
 
 #define DEBUG_TYPE "sh-mccodeemitter"
@@ -48,8 +46,7 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
   MCContext &Ctx;
 
 public:
-  SuperHMCCodeEmitter(const MCInstrInfo &, MCContext &ctx)
-    : Ctx(ctx) {}
+  SuperHMCCodeEmitter(const MCInstrInfo &, MCContext &ctx) : Ctx(ctx) {}
   SuperHMCCodeEmitter(const SuperHMCCodeEmitter &) = delete;
   SuperHMCCodeEmitter &operator=(const SuperHMCCodeEmitter &) = delete;
   ~SuperHMCCodeEmitter() override = default;
@@ -72,27 +69,25 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
 
   unsigned getExprOpValue(const MCInst &MI, const MCExpr *Expr,
                           SmallVectorImpl<MCFixup> &Fixups,
-                          const MCSubtargetInfo &STI,
-                          int64_t Shift) const;
+                          const MCSubtargetInfo &STI, int64_t Shift) const;
 
   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
-                          SmallVectorImpl<MCFixup> &Fixups,
-                          const MCSubtargetInfo &STI) const;
-  
+                                  SmallVectorImpl<MCFixup> &Fixups,
+                                  const MCSubtargetInfo &STI) const;
+
   // Displacement
-  template<int Scale>
+  template <int Scale>
   unsigned getDispOpValue(const MCInst &MI, unsigned OpNo,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
 
   // PC-relative displacement.
-  template<int Scale>
+  template <int Scale>
   unsigned getPCRelOpValue(const MCInst &MI, unsigned OpNo,
-                          SmallVectorImpl<MCFixup> &Fixups,
-                          const MCSubtargetInfo &STI) const;
+                           SmallVectorImpl<MCFixup> &Fixups,
+                           const MCSubtargetInfo &STI) const;
 
-  unsigned getOpBits(const MCInst &MI,
-                     SmallVectorImpl<MCFixup> &Fixups,
+  unsigned getOpBits(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups,
                      const MCSubtargetInfo &STI) const;
 };
 
@@ -105,17 +100,17 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
 // 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)
     return true;
-  
+
   // Other SH2A 32-bit instructions
   if ((Opcode & 0xF00F) == 0x3001)
     return true;
 
   // Opcodes bigger than 0xFFFF are always 32-bits.
-  return Opcode > 0xFFFF; 
+  return Opcode > 0xFFFF;
 }
 
 // Helper that gets the bits for the given instruction.
@@ -124,25 +119,27 @@ unsigned SuperHMCCodeEmitter::getOpBits(const MCInst &MI,
                                         const MCSubtargetInfo &STI) const {
   MCInst Inst = MCInst();
   Inst.setOpcode(MI.getOpcode());
-  for(unsigned i = 0; i < MI.getNumOperands(); i++) {
+  for (unsigned i = 0; i < MI.getNumOperands(); i++) {
     Inst.addOperand(MCOperand::createImm(0));
   }
 
   return getBinaryCodeForInstr(Inst, Fixups, STI);
 }
 
-// @getFixupForOpcode - Helper that gets the neccesary fixup for 
+// @getFixupForOpcode - Helper that gets the neccesary fixup for
 // the given opcode.
 // This is neccesary due to the various opcodes that access memory
 // have different scaling factors applied.
-static MCFixup getFixupForOpcode(unsigned Opcode, const MCExpr *Expr, MCContext &Ctx) {
+static MCFixup getFixupForOpcode(unsigned Opcode, const MCExpr *Expr,
+                                 MCContext &Ctx) {
 
   // NOTE:  A few (DSP and SH2A) instructions are 32-bits wide.
   //        We handle those quite crudely.
   MCFixupKind Kind = isOpcode32(Opcode) ? FK_Data_4 : FK_Data_2;
 
-  switch(Opcode) {
-  default: break;
+  switch (Opcode) {
+  default:
+    break;
 
   // disp4 * 2
   case SH::MOVWL4:
@@ -190,23 +187,24 @@ static MCFixup getFixupForOpcode(unsigned Opcode, const MCExpr *Expr, MCContext
 }
 
 void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
-                                           SmallVectorImpl<char> &CB,
-                                           SmallVectorImpl<MCFixup> &Fixups,
-                                           const MCSubtargetInfo &STI) const {
+                                            SmallVectorImpl<char> &CB,
+                                            SmallVectorImpl<MCFixup> &Fixups,
+                                            const MCSubtargetInfo &STI) const {
   uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
 
   // NOTE:  All base instructions are 16-bit in SH ASM
-  //        But some instructions may be 32-bit for eg. SH2A or the DSP extensions.
-  //        This is ugly, but it'll work.
+  //        But some instructions may be 32-bit for eg. SH2A or the DSP
+  //        extensions. This is ugly, but it'll work.
   if (isOpcode32(OpCode)) {
-    support::endian::write(CB, (uint32_t)OpCode, Ctx.getAsmInfo().isLittleEndian()
-                                        ? llvm::endianness::little
-                                        : llvm::endianness::big);
+    support::endian::write(CB, (uint32_t)OpCode,
+                           Ctx.getAsmInfo().isLittleEndian()
+                               ? llvm::endianness::little
+                               : llvm::endianness::big);
   } else {
-    support::endian::write(CB, (uint16_t)OpCode, Ctx.getAsmInfo().isLittleEndian()
-                                        ? llvm::endianness::little
-                                        : llvm::endianness::big);
-
+    support::endian::write(CB, (uint16_t)OpCode,
+                           Ctx.getAsmInfo().isLittleEndian()
+                               ? llvm::endianness::little
+                               : llvm::endianness::big);
   }
   ++MCNumEmitted;
 }
@@ -218,9 +216,10 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
 //                              Branch Target
 //===----------------------------------------------------------------------===//
 
-unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
-                                                     SmallVectorImpl<MCFixup> &Fixups,
-                                                     const MCSubtargetInfo &STI) const {
+unsigned
+SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+                                            SmallVectorImpl<MCFixup> &Fixups,
+                                            const MCSubtargetInfo &STI) const {
   return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
 }
 
@@ -231,10 +230,10 @@ unsigned SuperHMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned
 //                                Displacement
 //===----------------------------------------------------------------------===//
 
-template<int Scale>
+template <int Scale>
 unsigned SuperHMCCodeEmitter::getDispOpValue(const MCInst &MI, unsigned OpNo,
-                                              SmallVectorImpl<MCFixup> &Fixups,
-                                              const MCSubtargetInfo &STI) const {
+                                             SmallVectorImpl<MCFixup> &Fixups,
+                                             const MCSubtargetInfo &STI) const {
   // Skip base register if found.
   if (MI.getOperand(OpNo).isReg())
     OpNo++;
@@ -255,10 +254,11 @@ unsigned SuperHMCCodeEmitter::getDispOpValue(const MCInst &MI, unsigned OpNo,
 //                          PC-Relative Displacement
 //===----------------------------------------------------------------------===//
 
-template<int Scale>
-unsigned SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
-                                              SmallVectorImpl<MCFixup> &Fixups,
-                                              const MCSubtargetInfo &STI) const {
+template <int Scale>
+unsigned
+SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
+                                     SmallVectorImpl<MCFixup> &Fixups,
+                                     const MCSubtargetInfo &STI) const {
   auto MO = MI.getOperand(OpNo);
   if (MO.isImm())
     return MO.getImm() / Scale;
@@ -267,21 +267,25 @@ unsigned SuperHMCCodeEmitter::getPCRelOpValue(const MCInst &MI, unsigned OpNo,
   return getExprOpValue(MI, MO.getExpr(), Fixups, STI, Scale);
 }
 
-unsigned 
-SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
-                                    SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI, 
-                                    int64_t Shift) const {
+unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI,
+                                             const MCExpr *Expr,
+                                             SmallVectorImpl<MCFixup> &Fixups,
+                                             const MCSubtargetInfo &STI,
+                                             int64_t Shift) const {
   if (!Expr)
     return 0;
 
-  switch(Expr->getKind()) {
+  switch (Expr->getKind()) {
   case MCExpr::ExprKind::Binary: {
-    unsigned Res = getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(), Fixups, STI, Shift);
-    Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(), Fixups, STI, Shift);
+    unsigned Res =
+        getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getLHS(),
+                       Fixups, STI, Shift);
+    Res += getExprOpValue(MI, static_cast<const MCBinaryExpr *>(Expr)->getRHS(),
+                          Fixups, STI, Shift);
     return Res;
   }
   case MCExpr::ExprKind::Target: {
-    llvm_unreachable("TODO"); 
+    llvm_unreachable("TODO");
   }
   case MCExpr::ExprKind::Specifier: {
     const MCSpecifierExpr *Spec = static_cast<const MCSpecifierExpr *>(Expr);
@@ -303,10 +307,10 @@ SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCExpr *Expr,
 
 /// getMachineOpValue - Return binary encoding of operand. If the machine
 /// operand requires relocation, record the relocation and return zero.
-unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI, 
-                             const MCOperand &MO,
-                             SmallVectorImpl<MCFixup> &Fixups,
-                             const MCSubtargetInfo &STI) const {
+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());
 
@@ -318,6 +322,6 @@ unsigned SuperHMCCodeEmitter::getMachineOpValue(const MCInst &MI,
 }
 
 MCCodeEmitter *llvm::createSuperHMCCodeEmitter(const MCInstrInfo &MCII,
-                                              MCContext &Ctx) {
+                                               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 8aaa8a3040d43..1e6d469e79c9a 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.cpp
@@ -107,12 +107,13 @@ LLVMInitializeSuperHTargetMC() {
 
     // 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);
+    TargetRegistry::RegisterObjectTargetStreamer(*T,
+                                                 createTargetObjectStreamer);
 
     // Register the asm streamer.
     TargetRegistry::RegisterAsmTargetStreamer(*T, createTargetAsmStreamer);
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
index 5d060e597c149..6620af23f96a7 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCTargetDesc.h
@@ -34,14 +34,16 @@ class raw_ostream;
 class raw_pwrite_stream;
 
 MCCodeEmitter *createSuperHMCCodeEmitter(const MCInstrInfo &MCII,
-                                              MCContext &Ctx);
+                                         MCContext &Ctx);
 
-MCAsmBackend *createSuperHAsmBackend(const Target &T, const MCSubtargetInfo &STI,
-                                    const MCRegisterInfo &MRI,
-                                    const MCTargetOptions &Options);
+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);
+} // namespace llvm
 
 #define GET_REGINFO_ENUM
 #include "SuperHGenRegisterInfo.inc"
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
index 86e98b93b96a5..3e9aff7835a02 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
@@ -17,14 +17,15 @@
 
 using namespace llvm;
 
-SuperHTargetStreamer::SuperHTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
+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)
+                                                 const MCSubtargetInfo &STI)
     : SuperHTargetStreamer(S) {
   ELFObjectWriter &W = getStreamer().getWriter();
   unsigned EFlags = W.getELFHeaderEFlags();
diff --git a/llvm/lib/Target/SuperH/SuperH.h b/llvm/lib/Target/SuperH/SuperH.h
index efd8275d96c02..a779b58563608 100644
--- a/llvm/lib/Target/SuperH/SuperH.h
+++ b/llvm/lib/Target/SuperH/SuperH.h
@@ -25,7 +25,8 @@ class MachineInstr;
 class PassRegistry;
 class SuperHTargetMachine;
 
-FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel);
+FunctionPass *createSuperHISelDag(SuperHTargetMachine &TM,
+                                  CodeGenOptLevel OptLevel);
 FunctionPass *createSuperHFillDelaySlotsPass();
 FunctionPass *createSuperHConstantIslandPass();
 FunctionPass *createSuperHExpandPseudoPass();
@@ -39,5 +40,4 @@ void initializeSuperHConstantIslandsPass(PassRegistry &);
 void initializeSuperHExpandPseudoPass(PassRegistry &);
 } // namespace llvm
 
-
 #endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
index 7ae610276fbf4..aae05b5dabdaf 100644
--- a/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
+++ b/llvm/lib/Target/SuperH/SuperHAsmPrinter.cpp
@@ -38,7 +38,6 @@ class SuperHAsmPrinter : public AsmPrinter {
   static char ID;
 
 private:
-
   /// MCP - Keep a pointer to constantpool entries of the current
   /// MachineFunction.
   const MachineConstantPool *MCP;
@@ -50,16 +49,16 @@ class SuperHAsmPrinter : public AsmPrinter {
   /// Set of globals in PromotedGlobals that we've emitted labels for.
   /// We need to emit labels even for promoted globals so that DWARF
   /// debug info can link properly.
-  SmallPtrSet<const GlobalVariable*,2> EmittedPromotedGlobalLabels;
+  SmallPtrSet<const GlobalVariable *, 2> EmittedPromotedGlobalLabels;
 
-	SuperHTargetStreamer &getTargetStreamer() {
-		return static_cast<SuperHTargetStreamer &>(
-			*OutStreamer->getTargetStreamer());
-	}
+  SuperHTargetStreamer &getTargetStreamer() {
+    return static_cast<SuperHTargetStreamer &>(
+        *OutStreamer->getTargetStreamer());
+  }
 
 public:
   explicit SuperHAsmPrinter(TargetMachine &TM,
-                           std::unique_ptr<MCStreamer> Streamer)
+                            std::unique_ptr<MCStreamer> Streamer)
       : AsmPrinter(TM, std::move(Streamer), ID), MCP(nullptr) {}
 
   StringRef getPassName() const override { return "SuperH Assembly Printer"; }
@@ -73,7 +72,7 @@ class SuperHAsmPrinter : public AsmPrinter {
   void emitInstruction(const MachineInstr *MI) override;
 
   // We emit them ourselves.
-  void emitConstantPool() override { }
+  void emitConstantPool() override {}
   void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
 
   static std::string getRegisterName(MCRegister Reg) {
@@ -122,7 +121,8 @@ static uint8_t getModifierSpecifier(SHCP::SHCPModifier Modifier) {
 //                                  Operands
 //===----------------------------------------------------------------------===//
 
-void SuperHAsmPrinter::printOperand(const MachineInstr *MI, int OpNo, raw_ostream &O) {
+void SuperHAsmPrinter::printOperand(const MachineInstr *MI, int OpNo,
+                                    raw_ostream &O) {
   const MachineOperand &MO = MI->getOperand(OpNo);
 
   switch (MO.getType()) {
@@ -147,7 +147,7 @@ void SuperHAsmPrinter::printOperand(const MachineInstr *MI, int OpNo, raw_ostrea
 }
 
 bool SuperHAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) {
+                                       const char *ExtraCode, raw_ostream &O) {
   if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
     return false;
 
@@ -160,8 +160,10 @@ bool SuperHAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
   return false;
 }
 
-bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) {
+bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
+                                             unsigned OpNo,
+                                             const char *ExtraCode,
+                                             raw_ostream &O) {
   if (ExtraCode && ExtraCode[0])
     return true; // Unknown modifier
 
@@ -182,14 +184,15 @@ bool SuperHAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned Op
 //                                Constant Pool
 //===----------------------------------------------------------------------===//
 
-void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
+void SuperHAsmPrinter::emitMachineConstantPoolValue(
+    MachineConstantPoolValue *MCPV) {
   const DataLayout &DL = getDataLayout();
   int Size = DL.getTypeAllocSize(MCPV->getType());
   if (Size < 4)
     Size = 4;
 
   // Handle promoted constants (eg. immediates that don't fit in 8 bits).
-  SuperHConstantPoolValue *SCPV = static_cast<SuperHConstantPoolValue*>(MCPV);
+  SuperHConstantPoolValue *SCPV = static_cast<SuperHConstantPoolValue *>(MCPV);
   if (SCPV->isPromotedGlobal()) {
     auto *SCPC = cast<SuperHConstantPoolConstant>(SCPV);
     for (const auto *GV : SCPC->promotedGlobals()) {
@@ -200,38 +203,35 @@ void SuperHAsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MC
       }
     }
     return emitGlobalConstant(DL, SCPC->getPromotedGlobalInit());
-  } 
+  }
 
   MCSymbol *MCSym;
   if (SCPV->isBlockAddress()) {
     const BlockAddress *BA =
-      cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
+        cast<SuperHConstantPoolConstant>(SCPV)->getBlockAddress();
     MCSym = GetBlockAddressSymbol(BA);
 
-    LLVM_DEBUG(dbgs() << "Emit CPV BlockAddress " << SCPV->getLabelId() 
-                      << " \"" << MCSym->getName() << "\"...\n");
+    LLVM_DEBUG(dbgs() << "Emit CPV BlockAddress " << SCPV->getLabelId() << " \""
+                      << MCSym->getName() << "\"...\n");
 
   } else if (SCPV->isGlobalValue()) {
     const GlobalValue *GV = cast<SuperHConstantPoolConstant>(SCPV)->getGV();
     MCSym = getSymbolPreferLocal(*GV);
 
-    LLVM_DEBUG(dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() 
-                      << " \"" << MCSym->getName() << "\"...\n");
-  
+    LLVM_DEBUG(dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() << " \""
+                      << MCSym->getName() << "\"...\n");
+
   } else {
     assert(SCPV->isExtSymbol() && "unrecognized constant pool value");
     auto Sym = cast<SuperHConstantPoolSymbol>(SCPV)->getSymbol();
     MCSym = GetExternalSymbolSymbol(Sym);
 
-    LLVM_DEBUG(dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() 
-                      << " \"" << MCSym->getName() << "\"...\n");
+    LLVM_DEBUG(dbgs() << "Emit CPV GlobalValue " << SCPV->getLabelId() << " \""
+                      << MCSym->getName() << "\"...\n");
   }
 
   // Create an MCSymbol for the reference.
-  const MCExpr *Expr = MCSymbolRefExpr::create(
-    MCSym,
-    OutContext
-  );
+  const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, OutContext);
   OutStreamer->emitValue(Expr, Size);
 }
 
@@ -250,7 +250,6 @@ void SuperHAsmPrinter::emitFunctionBodyEnd() {
   OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
 }
 
-
 void SuperHAsmPrinter::emitInstruction(const MachineInstr *MI) {
   const SuperHSubtarget &STI = MF->getSubtarget<SuperHSubtarget>();
   const DataLayout &DL = getDataLayout();
@@ -276,7 +275,7 @@ void SuperHAsmPrinter::emitInstruction(const MachineInstr *MI) {
 
   case SH::CONSTPOOL_ENTRY: {
     unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
-    unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
+    unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
 
     // If this is the first entry of the pool, mark it.
     if (!InConstantPool) {
diff --git a/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
index 3a139ba14acf0..1e97ac7729b3c 100644
--- a/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.cpp
@@ -52,10 +52,10 @@ unsigned SuperHBasicBlockUtils::getOffsetOf(MachineInstr *MI) const {
 /// isBBInRange - Returns true if the distance between specific MI and
 /// specific BB can fit in MI's displacement field.
 bool SuperHBasicBlockUtils::isBBInRange(MachineInstr *MI,
-                                     MachineBasicBlock *DestBB,
-                                     unsigned MaxDisp) const {
-  unsigned PCAdj      = 4;
-  unsigned BrOffset   = getOffsetOf(MI) + PCAdj;
+                                        MachineBasicBlock *DestBB,
+                                        unsigned MaxDisp) const {
+  unsigned PCAdj = 4;
+  unsigned BrOffset = getOffsetOf(MI) + PCAdj;
   unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
 
   LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB)
@@ -66,10 +66,10 @@ bool SuperHBasicBlockUtils::isBBInRange(MachineInstr *MI,
 
   if (BrOffset <= DestOffset) {
     // Branch before the Dest.
-    if (DestOffset-BrOffset <= MaxDisp)
+    if (DestOffset - BrOffset <= MaxDisp)
       return true;
   } else {
-    if (BrOffset-DestOffset <= MaxDisp)
+    if (BrOffset - DestOffset <= MaxDisp)
       return true;
   }
   return false;
@@ -81,12 +81,12 @@ void SuperHBasicBlockUtils::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
 
   unsigned BBNum = BB->getNumber();
   LLVM_DEBUG(dbgs() << "Adjust block:\n"
-             << " - name: " << BB->getName() << "\n"
-             << " - number: " << BB->getNumber() << "\n"
-             << " - function: " << MF.getName() << "\n"
-             << "   - blocks: " << MF.getNumBlockIDs() << "\n");
+                    << " - name: " << BB->getName() << "\n"
+                    << " - number: " << BB->getNumber() << "\n"
+                    << " - function: " << MF.getName() << "\n"
+                    << "   - blocks: " << MF.getNumBlockIDs() << "\n");
 
-  for(unsigned i = BBNum + 1, e = MF.getNumBlockIDs(); i < e; ++i) {
+  for (unsigned i = BBNum + 1, e = MF.getNumBlockIDs(); i < e; ++i) {
     // Get the offset and known bits at the end of the layout predecessor.
     // Include the alignment of the current block.
     const Align Align = MF.getBlockNumbered(i)->getAlignment();
@@ -96,8 +96,7 @@ void SuperHBasicBlockUtils::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
     // This is where block i begins.  Stop if the offset is already correct,
     // and we have updated 2 blocks.  This is the maximum number of blocks
     // changed before calling this function.
-    if (i > BBNum + 2 &&
-        BBInfo[i].Offset == Offset &&
+    if (i > BBNum + 2 && BBInfo[i].Offset == Offset &&
         BBInfo[i].KnownBits == KnownBits)
       break;
 
@@ -106,5 +105,4 @@ void SuperHBasicBlockUtils::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
   }
 }
 
-
 } // namespace llvm
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
index f0039cbc5eb7f..ce31e86cdb813 100644
--- a/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHBasicBlockInfo.h
@@ -116,7 +116,7 @@ class SuperHBasicBlockUtils {
 public:
   SuperHBasicBlockUtils(MachineFunction &MF) : MF(MF) {
     TII =
-      static_cast<const SuperHInstrInfo*>(MF.getSubtarget().getInstrInfo());
+        static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
   }
 
   void computeAllBlockSizes() {
@@ -149,7 +149,6 @@ class SuperHBasicBlockUtils {
   void clear() { BBInfo.clear(); }
 
   BBInfoVector &getBBInfo() { return BBInfo; }
-
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
index 8703f20fd2c1d..99d42939a603f 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
+++ b/llvm/lib/Target/SuperH/SuperHConstantIslandPass.cpp
@@ -16,199 +16,191 @@
 #include "SuperHBasicBlockInfo.h"
 #include "SuperHMachineFunctionInfo.h"
 #include "SuperHSubtarget.h"
-#include "llvm/CodeGen/MachineDominators.h"
 #include "llvm/CodeGen/LivePhysRegs.h"
+#include "llvm/CodeGen/MachineDominators.h"
 #include <memory>
 using namespace llvm;
 
 #define DEBUG_TYPE "sh-cp-islands"
 
-#define SH_CP_ISLANDS_OPT_NAME \
+#define SH_CP_ISLANDS_OPT_NAME                                                 \
   "SH constant island placement and branch shortening pass"
 
 static cl::opt<unsigned>
-CPMaxIteration("sh-constant-island-max-iteration", cl::Hidden, cl::init(30),
-          cl::desc("The max number of iteration for converge"));
+    CPMaxIteration("sh-constant-island-max-iteration", cl::Hidden, cl::init(30),
+                   cl::desc("The max number of iteration for converge"));
 
 namespace {
 
-  /// SuperHConstantIslands - Due to limited PC-relative displacements, SH
-  /// requires constant pool entries to be scattered among the instructions
-  /// inside a function.  To do this, it completely ignores the normal LLVM
-  /// constant pool; instead, it places constants wherever it feels like with
-  /// special instructions.
-  ///
-  /// The terminology used in this pass includes:
-  ///   Islands - Clumps of constants placed in the function.
-  ///   Water   - Potential places where an island could be formed.
-  ///   CPE     - A constant pool entry that has been placed somewhere, which
-  ///             tracks a list of users.
-  class SuperHConstantIslands : public MachineFunctionPass {
-  public:
-    static char ID;
-
-  private:
-    std::unique_ptr<SuperHBasicBlockUtils> BBUtils = nullptr;
-
-    /// WaterList - A sorted list of basic blocks where islands could be placed
-    /// (i.e. blocks that don't fall through to the following block, due
-    /// to a return, unreachable, or unconditional branch).
-    std::vector<MachineBasicBlock*> WaterList;
-
-    /// NewWaterList - The subset of WaterList that was created since the
-    /// previous iteration by inserting unconditional branches.
-    SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
-
-    using water_iterator = std::vector<MachineBasicBlock *>::iterator;
-
-    /// CPUser - One user of a constant pool, keeping the machine instruction
-    /// pointer, the constant pool being referenced, and the max displacement
-    /// allowed from the instruction to the CP.  The HighWaterMark records the
-    /// highest basic block where a new CPEntry can be placed.  To ensure this
-    /// pass terminates, the CP entries are initially placed at the end of the
-    /// function and then move monotonically to lower addresses.  The
-    /// exception to this rule is when the current CP entry for a particular
-    /// CPUser is out of range, but there is another CP entry for the same
-    /// constant value in range.  We want to use the existing in-range CP
-    /// entry, but if it later moves out of range, the search for new water
-    /// should resume where it left off.  The HighWaterMark is used to record
-    /// that point.
-    struct CPUser {
-      MachineInstr *MI;
-      MachineInstr *CPEMI;
-      MachineBasicBlock *HighWaterMark;
-      unsigned MaxDisp;
-      bool NegOk;
-      bool IsSoImm;
-      bool KnownAlignment = false;
-
-      CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,
-             bool neg, bool soimm)
+/// SuperHConstantIslands - Due to limited PC-relative displacements, SH
+/// requires constant pool entries to be scattered among the instructions
+/// inside a function.  To do this, it completely ignores the normal LLVM
+/// constant pool; instead, it places constants wherever it feels like with
+/// special instructions.
+///
+/// The terminology used in this pass includes:
+///   Islands - Clumps of constants placed in the function.
+///   Water   - Potential places where an island could be formed.
+///   CPE     - A constant pool entry that has been placed somewhere, which
+///             tracks a list of users.
+class SuperHConstantIslands : public MachineFunctionPass {
+public:
+  static char ID;
+
+private:
+  std::unique_ptr<SuperHBasicBlockUtils> BBUtils = nullptr;
+
+  /// WaterList - A sorted list of basic blocks where islands could be placed
+  /// (i.e. blocks that don't fall through to the following block, due
+  /// to a return, unreachable, or unconditional branch).
+  std::vector<MachineBasicBlock *> WaterList;
+
+  /// NewWaterList - The subset of WaterList that was created since the
+  /// previous iteration by inserting unconditional branches.
+  SmallPtrSet<MachineBasicBlock *, 4> NewWaterList;
+
+  using water_iterator = std::vector<MachineBasicBlock *>::iterator;
+
+  /// CPUser - One user of a constant pool, keeping the machine instruction
+  /// pointer, the constant pool being referenced, and the max displacement
+  /// allowed from the instruction to the CP.  The HighWaterMark records the
+  /// highest basic block where a new CPEntry can be placed.  To ensure this
+  /// pass terminates, the CP entries are initially placed at the end of the
+  /// function and then move monotonically to lower addresses.  The
+  /// exception to this rule is when the current CP entry for a particular
+  /// CPUser is out of range, but there is another CP entry for the same
+  /// constant value in range.  We want to use the existing in-range CP
+  /// entry, but if it later moves out of range, the search for new water
+  /// should resume where it left off.  The HighWaterMark is used to record
+  /// that point.
+  struct CPUser {
+    MachineInstr *MI;
+    MachineInstr *CPEMI;
+    MachineBasicBlock *HighWaterMark;
+    unsigned MaxDisp;
+    bool NegOk;
+    bool IsSoImm;
+    bool KnownAlignment = false;
+
+    CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp, bool neg,
+           bool soimm)
         : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(neg), IsSoImm(soimm) {
-        HighWaterMark = CPEMI->getParent();
-      }
+      HighWaterMark = CPEMI->getParent();
+    }
 
-      /// getMaxDisp - Returns the maximum displacement supported by MI.
-      /// Correct for unknown alignment.
-      /// Conservatively subtract 2 bytes to handle weird alignment effects.
-      unsigned getMaxDisp() const {
-        return (KnownAlignment ? MaxDisp : MaxDisp - 2) - 2;
-      }
-    };
+    /// getMaxDisp - Returns the maximum displacement supported by MI.
+    /// Correct for unknown alignment.
+    /// Conservatively subtract 2 bytes to handle weird alignment effects.
+    unsigned getMaxDisp() const {
+      return (KnownAlignment ? MaxDisp : MaxDisp - 2) - 2;
+    }
+  };
 
-    /// CPUsers - Keep track of all of the machine instructions that use various
-    /// constant pools and their max displacement.
-    std::vector<CPUser> CPUsers;
+  /// CPUsers - Keep track of all of the machine instructions that use various
+  /// constant pools and their max displacement.
+  std::vector<CPUser> CPUsers;
 
-    /// CPEntry - One per constant pool entry, keeping the machine instruction
-    /// pointer, the constpool index, and the number of CPUser's which
-    /// reference this entry.
-    struct CPEntry {
-      MachineInstr *CPEMI;
-      unsigned CPI;
-      unsigned RefCount;
+  /// CPEntry - One per constant pool entry, keeping the machine instruction
+  /// pointer, the constpool index, and the number of CPUser's which
+  /// reference this entry.
+  struct CPEntry {
+    MachineInstr *CPEMI;
+    unsigned CPI;
+    unsigned RefCount;
 
-      CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0)
+    CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0)
         : CPEMI(cpemi), CPI(cpi), RefCount(rc) {}
-    };
-
-    /// CPEntries - Keep track of all of the constant pool entry machine
-    /// instructions. For each original constpool index (i.e. those that existed
-    /// upon entry to this pass), it keeps a vector of entries.  Original
-    /// elements are cloned as we go along; the clones are put in the vector of
-    /// the original element, but have distinct CPIs.
-    ///
-    /// The first half of CPEntries contains generic constants, the second half
-    /// contains jump tables. Use getCombinedIndex on a generic CPEMI to look up
-    /// which vector it will be in here.
-    std::vector<std::vector<CPEntry>> CPEntries;
-
-    /// ImmBranch - One per immediate branch, keeping the machine instruction
-    /// pointer, conditional or unconditional, the max displacement,
-    /// and (if isCond is true) the corresponding unconditional branch
-    /// opcode.
-    struct ImmBranch {
-      MachineInstr *MI;
-      unsigned MaxDisp : 12;
-
-      ImmBranch(MachineInstr *mi, unsigned maxdisp)
-        : MI(mi), MaxDisp(maxdisp) {}
-    };
-
-    /// ImmBranches - Keep track of all the immediate branch instructions.
-    std::vector<ImmBranch> ImmBranches;
-
-    MachineFunction *MF;
-    MachineConstantPool *MCP;
-    const SuperHInstrInfo *TII;
-    const SuperHSubtarget *STI;
-    SuperHMachineFunctionInfo *SFI;
-    MachineDominatorTree *DT = nullptr;
-    bool isPIC;
-
-  public:
-
-    SuperHConstantIslands() : MachineFunctionPass(ID) {}
-
-    bool runOnMachineFunction(MachineFunction &MF) override;
-
-    void getAnalysisUsage(AnalysisUsage &AU) const override {
-      AU.addRequired<MachineDominatorTreeWrapperPass>();
-      MachineFunctionPass::getAnalysisUsage(AU);
-    }
+  };
 
-    MachineFunctionProperties getRequiredProperties() const override {
-      return MachineFunctionProperties().setNoVRegs();
-    }
+  /// CPEntries - Keep track of all of the constant pool entry machine
+  /// instructions. For each original constpool index (i.e. those that existed
+  /// upon entry to this pass), it keeps a vector of entries.  Original
+  /// elements are cloned as we go along; the clones are put in the vector of
+  /// the original element, but have distinct CPIs.
+  ///
+  /// The first half of CPEntries contains generic constants, the second half
+  /// contains jump tables. Use getCombinedIndex on a generic CPEMI to look up
+  /// which vector it will be in here.
+  std::vector<std::vector<CPEntry>> CPEntries;
+
+  /// ImmBranch - One per immediate branch, keeping the machine instruction
+  /// pointer, conditional or unconditional, the max displacement,
+  /// and (if isCond is true) the corresponding unconditional branch
+  /// opcode.
+  struct ImmBranch {
+    MachineInstr *MI;
+    unsigned MaxDisp : 12;
+
+    ImmBranch(MachineInstr *mi, unsigned maxdisp) : MI(mi), MaxDisp(maxdisp) {}
+  };
 
-    StringRef getPassName() const override {
-      return SH_CP_ISLANDS_OPT_NAME;
-    }
+  /// ImmBranches - Keep track of all the immediate branch instructions.
+  std::vector<ImmBranch> ImmBranches;
 
-  private:
-    bool BBHasFallthrough(MachineBasicBlock *MBB);
-    void doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs);
-    CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
-    Align getCPEAlign(const MachineInstr *CPEMI);
-    void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs);
-    MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI);
-    void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
-    bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI);
-    unsigned getCombinedIndex(const MachineInstr *CPEMI);
-    int findInRangeCPEntry(CPUser& U, unsigned UserOffset);
-    bool findAvailableWater(CPUser&U, unsigned UserOffset,
-                            water_iterator &WaterIter, bool CloserWater);
-    void createNewWater(unsigned CPUserIndex, unsigned UserOffset,
-                        MachineBasicBlock *&NewMBB);
-    bool handleConstantPoolUser(unsigned CPUserIndex, bool CloserWater);
-    void removeDeadCPEMI(MachineInstr *CPEMI);
-    bool removeUnusedCPEntries();
-    bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
-                          MachineInstr *CPEMI, unsigned Disp, bool NegOk,
-                          bool DoDump = false);
-    bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water,
-                        CPUser &U, unsigned &Growth);
-    bool fixupImmediateBr(ImmBranch &Br);
-
-    unsigned getUserOffset(CPUser&) const;
-    void verify();
-
-    bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
-                         unsigned Disp, bool NegativeOK, bool IsSoImm = false);
-    bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
-                         const CPUser &U) {
-      return isOffsetInRange(UserOffset, TrialOffset,
-                             U.getMaxDisp(), U.NegOk, U.IsSoImm);
-    }
+  MachineFunction *MF;
+  MachineConstantPool *MCP;
+  const SuperHInstrInfo *TII;
+  const SuperHSubtarget *STI;
+  SuperHMachineFunctionInfo *SFI;
+  MachineDominatorTree *DT = nullptr;
+  bool isPIC;
 
-  };
+public:
+  SuperHConstantIslands() : MachineFunctionPass(ID) {}
 
-} // end anonymous namespace
+  bool runOnMachineFunction(MachineFunction &MF) override;
 
-char SuperHConstantIslands::ID = 0;
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.addRequired<MachineDominatorTreeWrapperPass>();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
 
+  MachineFunctionProperties getRequiredProperties() const override {
+    return MachineFunctionProperties().setNoVRegs();
+  }
 
+  StringRef getPassName() const override { return SH_CP_ISLANDS_OPT_NAME; }
+
+private:
+  bool BBHasFallthrough(MachineBasicBlock *MBB);
+  void doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs);
+  CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
+  Align getCPEAlign(const MachineInstr *CPEMI);
+  void initializeFunctionInfo(const std::vector<MachineInstr *> &CPEMIs);
+  MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI);
+  void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
+  bool decrementCPEReferenceCount(unsigned CPI, MachineInstr *CPEMI);
+  unsigned getCombinedIndex(const MachineInstr *CPEMI);
+  int findInRangeCPEntry(CPUser &U, unsigned UserOffset);
+  bool findAvailableWater(CPUser &U, unsigned UserOffset,
+                          water_iterator &WaterIter, bool CloserWater);
+  void createNewWater(unsigned CPUserIndex, unsigned UserOffset,
+                      MachineBasicBlock *&NewMBB);
+  bool handleConstantPoolUser(unsigned CPUserIndex, bool CloserWater);
+  void removeDeadCPEMI(MachineInstr *CPEMI);
+  bool removeUnusedCPEntries();
+  bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
+                        MachineInstr *CPEMI, unsigned Disp, bool NegOk,
+                        bool DoDump = false);
+  bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water, CPUser &U,
+                      unsigned &Growth);
+  bool fixupImmediateBr(ImmBranch &Br);
+
+  unsigned getUserOffset(CPUser &) const;
+  void verify();
+
+  bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, unsigned Disp,
+                       bool NegativeOK, bool IsSoImm = false);
+  bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
+                       const CPUser &U) {
+    return isOffsetInRange(UserOffset, TrialOffset, U.getMaxDisp(), U.NegOk,
+                           U.IsSoImm);
+  }
+};
 
+} // end anonymous namespace
+
+char SuperHConstantIslands::ID = 0;
 
 //===----------------------------------------------------------------------===//
 //                                  HELPERS
@@ -248,9 +240,7 @@ static bool CompareMBBNumbers(const MachineBasicBlock *LHS,
 
 /// getDispRange - Returns the maximum displacement that can fit in
 /// the specific unconditional branch instruction.
-static inline unsigned getDispRange(int Opc) {
-  return ((1<<8)-1)*4;
-}
+static inline unsigned getDispRange(int Opc) { return ((1 << 8) - 1) * 4; }
 
 /// isOffsetInRange - Checks whether UserOffset (the location of a constant pool
 /// reference) is within MaxDisp of TrialOffset (a proposed location of a
@@ -259,8 +249,9 @@ static inline unsigned getDispRange(int Opc) {
 /// the mod 4 alignment of UserOffset is not known, the uncertainty must be
 /// subtracted from MaxDisp instead. CPUser::getMaxDisp() does that.
 bool SuperHConstantIslands::isOffsetInRange(unsigned UserOffset,
-                                         unsigned TrialOffset, unsigned MaxDisp,
-                                         bool NegativeOK, bool IsSoImm) {
+                                            unsigned TrialOffset,
+                                            unsigned MaxDisp, bool NegativeOK,
+                                            bool IsSoImm) {
   if (UserOffset <= TrialOffset) {
     // User before the Trial.
     if (TrialOffset - UserOffset <= MaxDisp)
@@ -308,8 +299,8 @@ Align SuperHConstantIslands::getCPEAlign(const MachineInstr *CPEMI) {
 ///
 /// Compute how much the function will grow by inserting a CPE after Water.
 bool SuperHConstantIslands::isWaterInRange(unsigned UserOffset,
-                                        MachineBasicBlock* Water, CPUser &U,
-                                        unsigned &Growth) {
+                                           MachineBasicBlock *Water, CPUser &U,
+                                           unsigned &Growth) {
   BBInfoVector &BBInfo = BBUtils->getBBInfo();
   const Align CPEAlign = getCPEAlign(U.CPEMI);
   const unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPEAlign);
@@ -348,14 +339,16 @@ bool SuperHConstantIslands::isWaterInRange(unsigned UserOffset,
 
 /// isCPEntryInRange - Returns true if the distance between specific MI and
 /// specific ConstPool entry instruction can fit in MI's displacement field.
-bool SuperHConstantIslands::isCPEntryInRange(MachineInstr *MI, unsigned UserOffset,
-                                      MachineInstr *CPEMI, unsigned MaxDisp,
-                                      bool NegOk, bool DoDump) {
+bool SuperHConstantIslands::isCPEntryInRange(MachineInstr *MI,
+                                             unsigned UserOffset,
+                                             MachineInstr *CPEMI,
+                                             unsigned MaxDisp, bool NegOk,
+                                             bool DoDump) {
   unsigned CPEOffset = BBUtils->getOffsetOf(CPEMI);
 
   if (DoDump) {
     LLVM_DEBUG({
-        BBInfoVector &BBInfo = BBUtils->getBBInfo();
+      BBInfoVector &BBInfo = BBUtils->getBBInfo();
       unsigned Block = MI->getParent()->getNumber();
       const BasicBlockInfo &BBI = BBInfo[Block];
       dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm()
@@ -423,17 +416,16 @@ bool SuperHConstantIslands::runOnMachineFunction(MachineFunction &mf) {
 
   // Perform the initial placement of the constant pool entries.  To start with,
   // we put them all at the end of the function.
-  std::vector<MachineInstr*> CPEMIs;
+  std::vector<MachineInstr *> CPEMIs;
   if (!MCP->isEmpty())
     doInitialConstPlacement(CPEMIs);
 
-
   // Iteratively place constant pool entries and fix up branches until there
   // is no change.
   unsigned NoCPIters = 0, NoBRIters = 0;
   while (true) {
-    LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << " with " <<
-                         CPUsers.size() << " entries..." << '\n');
+    LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << " with "
+                      << CPUsers.size() << " entries..." << '\n');
     bool CPChange = false;
     for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
       // For most inputs, it converges in no more than 5 iterations.
@@ -447,8 +439,8 @@ bool SuperHConstantIslands::runOnMachineFunction(MachineFunction &mf) {
     // appear as "new water" for the next iteration of constant pool placement.
     NewWaterList.clear();
 
-    LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << " with " <<
-                         ImmBranches.size() << " entries..." << '\n');
+    LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << " with "
+                      << ImmBranches.size() << " entries..." << '\n');
     bool BRChange = false;
     for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) {
       // Note: fixupImmediateBr can append to ImmBranches.
@@ -473,8 +465,8 @@ bool SuperHConstantIslands::runOnMachineFunction(MachineFunction &mf) {
 /// initializeFunctionInfo - Do the initial scan of the function, building up
 /// information about the sizes of each block, the location of all the water,
 /// and finding all of the constant pool users.
-void SuperHConstantIslands::
-initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
+void SuperHConstantIslands::initializeFunctionInfo(
+    const std::vector<MachineInstr *> &CPEMIs) {
 
   BBUtils->computeAllBlockSizes();
   BBInfoVector &BBInfo = BBUtils->getBBInfo();
@@ -520,9 +512,8 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
           break;
         }
 
-
         // Record this immediate branch.
-        unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
+        unsigned MaxOffs = ((1 << (Bits - 1)) - 1) * Scale;
         ImmBranches.push_back(ImmBranch(&I, MaxOffs));
       }
 
@@ -537,7 +528,7 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
 
           unsigned CPI = I.getOperand(op).getIndex();
           MachineInstr *CPEMI = CPEMIs[CPI];
-          unsigned MaxOffs = ((1 << 8)-1) * 4;
+          unsigned MaxOffs = ((1 << 8) - 1) * 4;
           CPUsers.push_back(CPUser(&I, CPEMI, MaxOffs, NegOk, IsSoImm));
 
           // Increment corresponding CPEntry reference count.
@@ -548,7 +539,6 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
           // Instructions can only use one CP entry, don't bother scanning the
           // rest of the operands.
           break;
-
         }
       }
     }
@@ -605,7 +595,7 @@ bool SuperHConstantIslands::removeUnusedCPEntries() {
 /// becomes 0 remove the entry and instruction.  Returns true if we removed
 /// the entry, false if we didn't.
 bool SuperHConstantIslands::decrementCPEReferenceCount(unsigned CPI,
-                                                    MachineInstr *CPEMI) {
+                                                       MachineInstr *CPEMI) {
   // Find the old entry. Eliminate it if it is no longer used.
   CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
   assert(CPE && "Unexpected!");
@@ -629,9 +619,9 @@ unsigned SuperHConstantIslands::getCombinedIndex(const MachineInstr *CPEMI) {
 /// 0 = no existing entry found
 /// 1 = entry found, and there were no code insertions or deletions
 /// 2 = entry found, and there were code insertions or deletions
-int SuperHConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) {
+int SuperHConstantIslands::findInRangeCPEntry(CPUser &U, unsigned UserOffset) {
   MachineInstr *UserMI = U.MI;
-  MachineInstr *CPEMI  = U.CPEMI;
+  MachineInstr *CPEMI = U.CPEMI;
 
   // Check to see if the CPE is already in-range.
   if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk,
@@ -677,10 +667,10 @@ int SuperHConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) {
 /// place in-range.  Return true if we changed any addresses (thus must run
 /// another pass of branch lengthening), false otherwise.
 bool SuperHConstantIslands::handleConstantPoolUser(unsigned CPUserIndex,
-                                                bool CloserWater) {
+                                                   bool CloserWater) {
   CPUser &U = CPUsers[CPUserIndex];
   MachineInstr *UserMI = U.MI;
-  MachineInstr *CPEMI  = U.CPEMI;
+  MachineInstr *CPEMI = U.CPEMI;
   unsigned CPI = getCombinedIndex(CPEMI);
   unsigned Size = CPEMI->getOperand(2).getImm();
   // Compute this only once, it's expensive.
@@ -689,8 +679,10 @@ bool SuperHConstantIslands::handleConstantPoolUser(unsigned CPUserIndex,
   // See if the current entry is within range, or there is a clone of it
   // in range.
   int result = findInRangeCPEntry(U, UserOffset);
-  if (result==1) return false;
-  else if (result==2) return true;
+  if (result == 1)
+    return false;
+  else if (result == 2)
+    return true;
 
   // No existing clone of this CPE is within range.
   // We will be generating a new clone.  Get a UID for it.
@@ -789,7 +781,7 @@ bool SuperHConstantIslands::handleConstantPoolUser(unsigned CPUserIndex,
 /// look up the corresponding CPEntry.
 SuperHConstantIslands::CPEntry *
 SuperHConstantIslands::findConstPoolEntry(unsigned CPI,
-                                       const MachineInstr *CPEMI) {
+                                          const MachineInstr *CPEMI) {
   std::vector<CPEntry> &CPEs = CPEntries[CPI];
   // Number of entries per constpool index should be small, just do a
   // linear search.
@@ -808,8 +800,8 @@ SuperHConstantIslands::findConstPoolEntry(unsigned CPI,
 /// move to a lower address, so search backward from the end of the list and
 /// prefer the first water that is in range.
 bool SuperHConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
-                                            water_iterator &WaterIter,
-                                            bool CloserWater) {
+                                               water_iterator &WaterIter,
+                                               bool CloserWater) {
   if (WaterList.empty())
     return false;
 
@@ -832,7 +824,7 @@ bool SuperHConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
     return false;
   for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();;
        --IP) {
-    MachineBasicBlock* WaterBB = *IP;
+    MachineBasicBlock *WaterBB = *IP;
     // Check if water is in range and is either at a lower address than the
     // current "high water mark" or a new water block that was created since
     // the previous iteration by inserting an unconditional branch.  In the
@@ -875,11 +867,11 @@ bool SuperHConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
 /// block following which the new island can be inserted (the WaterList
 /// is not adjusted).
 void SuperHConstantIslands::createNewWater(unsigned CPUserIndex,
-                                        unsigned UserOffset,
-                                        MachineBasicBlock *&NewMBB) {
+                                           unsigned UserOffset,
+                                           MachineBasicBlock *&NewMBB) {
   CPUser &U = CPUsers[CPUserIndex];
   MachineInstr *UserMI = U.MI;
-  MachineInstr *CPEMI  = U.CPEMI;
+  MachineInstr *CPEMI = U.CPEMI;
   const Align CPEAlign = getCPEAlign(CPEMI);
   MachineBasicBlock *UserMBB = UserMI->getParent();
   BBInfoVector &BBInfo = BBUtils->getBBInfo();
@@ -905,8 +897,7 @@ void SuperHConstantIslands::createNewWater(unsigned CPUserIndex,
       // but if the preceding conditional branch is out of range, the targets
       // will be exchanged, and the altered branch may be out of range, so the
       // machinery has to know about it.
-      BuildMI(UserMBB, DebugLoc(), TII->get(SH::BRA))
-          .addMBB(NewMBB);
+      BuildMI(UserMBB, DebugLoc(), TII->get(SH::BRA)).addMBB(NewMBB);
 
       unsigned MaxDisp = getDispRange(SH::BRA);
       ImmBranches.push_back(ImmBranch(&UserMBB->back(), MaxDisp));
@@ -948,11 +939,11 @@ void SuperHConstantIslands::createNewWater(unsigned CPUserIndex,
                     << " la=" << Log2(Align) << " kb=" << KnownBits
                     << " up=" << UPad << '\n');
 
-  unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +
-    CPEMI->getOperand(2).getImm();
+  unsigned EndInsertOffset =
+      BaseInsertOffset + 4 + UPad + CPEMI->getOperand(2).getImm();
   MachineBasicBlock::iterator MI = UserMI;
   ++MI;
-  unsigned CPUIndex = CPUserIndex+1;
+  unsigned CPUIndex = CPUserIndex + 1;
   unsigned NumCPUsers = CPUsers.size();
   for (unsigned Offset = UserOffset + TII->getInstSizeInBytes(*UserMI);
        Offset < BaseInsertOffset;
@@ -983,7 +974,8 @@ void SuperHConstantIslands::createNewWater(unsigned CPUserIndex,
 /// updateForInsertedWaterBlock - When a block is newly inserted into the
 /// machine function, it upsets all of the block numbers.  Renumber the blocks
 /// and update the arrays that parallel this numbering.
-void SuperHConstantIslands::updateForInsertedWaterBlock(MachineBasicBlock *NewBB) {
+void SuperHConstantIslands::updateForInsertedWaterBlock(
+    MachineBasicBlock *NewBB) {
   // Renumber the MBB's to keep them consecutive.
   NewBB->getParent()->RenumberBlocks(NewBB);
 
@@ -1000,7 +992,8 @@ void SuperHConstantIslands::updateForInsertedWaterBlock(MachineBasicBlock *NewBB
 /// Split the basic block containing MI into two blocks, which are joined by
 /// an unconditional branch.  Update data structures and renumber blocks to
 /// account for this change and returns the newly created block.
-MachineBasicBlock *SuperHConstantIslands::splitBlockBeforeInstr(MachineInstr *MI) {
+MachineBasicBlock *
+SuperHConstantIslands::splitBlockBeforeInstr(MachineInstr *MI) {
   MachineBasicBlock *OrigBB = MI->getParent();
 
   // Collect liveness information at MI.
@@ -1012,7 +1005,7 @@ MachineBasicBlock *SuperHConstantIslands::splitBlockBeforeInstr(MachineInstr *MI
 
   // Create a new MBB for the code after the OrigBB.
   MachineBasicBlock *NewBB =
-    MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
+      MF->CreateMachineBasicBlock(OrigBB->getBasicBlock());
   MachineFunction::iterator MBBI = ++OrigBB->getIterator();
   MF->insert(MBBI, NewBB);
 
@@ -1051,7 +1044,7 @@ MachineBasicBlock *SuperHConstantIslands::splitBlockBeforeInstr(MachineInstr *MI
   // when splitting before a conditional branch that is followed by an
   // unconditional branch - in that case we want to insert NewBB).
   water_iterator IP = llvm::lower_bound(WaterList, OrigBB, CompareMBBNumbers);
-  MachineBasicBlock* WaterBB = *IP;
+  MachineBasicBlock *WaterBB = *IP;
   if (WaterBB == OrigBB)
     WaterList.insert(std::next(IP), NewBB);
   else
@@ -1084,9 +1077,9 @@ MachineBasicBlock *SuperHConstantIslands::splitBlockBeforeInstr(MachineInstr *MI
 
 /// Perform the initial placement of the regular constant pool entries.
 /// To start with, we put them all at the end of the function.
-void
-SuperHConstantIslands::doInitialConstPlacement(std::vector<MachineInstr *> &CPEMIs) {
-  
+void SuperHConstantIslands::doInitialConstPlacement(
+    std::vector<MachineInstr *> &CPEMIs) {
+
   // Create the basic block to hold the CPE's.
   MachineBasicBlock *BB = MF->CreateMachineBasicBlock();
   MF->push_back(BB);
@@ -1129,8 +1122,10 @@ SuperHConstantIslands::doInitialConstPlacement(std::vector<MachineInstr *> &CPEM
     unsigned LogAlign = Log2(Alignment);
     MachineBasicBlock::iterator InsAt = InsPoint[LogAlign];
     MachineInstr *CPEMI =
-      BuildMI(*BB, InsAt, DebugLoc(), TII->get(SH::CONSTPOOL_ENTRY))
-        .addImm(i).addConstantPoolIndex(i).addImm(Size);
+        BuildMI(*BB, InsAt, DebugLoc(), TII->get(SH::CONSTPOOL_ENTRY))
+            .addImm(i)
+            .addConstantPoolIndex(i)
+            .addImm(Size);
     CPEMIs.push_back(CPEMI);
 
     // Ensure that future entries with higher alignment get inserted before
@@ -1180,6 +1175,5 @@ FunctionPass *llvm::createSuperHConstantIslandPass() {
   return new SuperHConstantIslands();
 }
 
-
 INITIALIZE_PASS(SuperHConstantIslands, "sh-cp-islands", SH_CP_ISLANDS_OPT_NAME,
                 false, false)
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
index e102c2438a600..0bdad4cb7b824 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.cpp
@@ -21,15 +21,16 @@ using namespace llvm;
 //===----------------------------------------------------------------------===//
 
 SuperHConstantPoolValue::SuperHConstantPoolValue(Type *Ty, unsigned id,
-                                           SHCP::SHCPKind kind,
-                                           SHCP::SHCPModifier modifier)
-  : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind), Modifier(modifier) {}
+                                                 SHCP::SHCPKind kind,
+                                                 SHCP::SHCPModifier modifier)
+    : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind),
+      Modifier(modifier) {}
 
 SuperHConstantPoolValue::SuperHConstantPoolValue(LLVMContext &C, unsigned id,
-                                           SHCP::SHCPKind kind,
-                                           SHCP::SHCPModifier modifier)
-  : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)),
-    LabelId(id), Kind(kind), Modifier(modifier) {}
+                                                 SHCP::SHCPKind kind,
+                                                 SHCP::SHCPModifier modifier)
+    : MachineConstantPoolValue((Type *)Type::getInt32Ty(C)), LabelId(id),
+      Kind(kind), Modifier(modifier) {}
 
 SuperHConstantPoolValue::~SuperHConstantPoolValue() = default;
 
@@ -48,19 +49,16 @@ StringRef SuperHConstantPoolValue::getModifierText() const {
 }
 
 int SuperHConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
-                                                    Align Alignment) {
+                                                       Align Alignment) {
   llvm_unreachable("Shouldn't be calling this directly!");
 }
 
-void
-SuperHConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
+void SuperHConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
   ID.AddInteger(LabelId);
 }
 
-bool
-SuperHConstantPoolValue::hasSameValue(SuperHConstantPoolValue *ACPV) {
-  if (ACPV->Kind == Kind &&
-      ACPV->Modifier == Modifier &&
+bool SuperHConstantPoolValue::hasSameValue(SuperHConstantPoolValue *ACPV) {
+  if (ACPV->Kind == Kind && ACPV->Modifier == Modifier &&
       ACPV->LabelId == LabelId) {
 
     // Two PC relative constpool entries containing the same GV address or
@@ -78,7 +76,8 @@ LLVM_DUMP_METHOD void SuperHConstantPoolValue::dump() const {
 #endif
 
 void SuperHConstantPoolValue::print(raw_ostream &O) const {
-  if (Modifier) O << "(" << getModifierText() << ")";
+  if (Modifier)
+    O << "(" << getModifierText() << ")";
 }
 
 
@@ -88,59 +87,55 @@ void SuperHConstantPoolValue::print(raw_ostream &O) const {
 // SuperHConstantPoolConstant
 //===----------------------------------------------------------------------===//
 
-SuperHConstantPoolConstant::SuperHConstantPoolConstant(Type *Ty,
-                                                 const Constant *C,
-                                                 unsigned ID,
-                                                 SHCP::SHCPKind Kind,
-                                                 SHCP::SHCPModifier Modifier)
-  : SuperHConstantPoolValue(Ty, ID, Kind, Modifier),
-    CVal(C) {}
-
-SuperHConstantPoolConstant::SuperHConstantPoolConstant(const Constant *C,
-                                                 unsigned ID,
-                                                 SHCP::SHCPKind Kind,
-                                                 SHCP::SHCPModifier Modifier)
-  : SuperHConstantPoolValue((Type*)C->getType(), ID, Kind, Modifier),
-    CVal(C) {}
+SuperHConstantPoolConstant::SuperHConstantPoolConstant(
+    Type *Ty, const Constant *C, unsigned ID, SHCP::SHCPKind Kind,
+    SHCP::SHCPModifier Modifier)
+    : SuperHConstantPoolValue(Ty, ID, Kind, Modifier), CVal(C) {}
+
+SuperHConstantPoolConstant::SuperHConstantPoolConstant(
+    const Constant *C, unsigned ID, SHCP::SHCPKind Kind,
+    SHCP::SHCPModifier Modifier)
+    : SuperHConstantPoolValue((Type *)C->getType(), ID, Kind, Modifier),
+      CVal(C) {}
 
 SuperHConstantPoolConstant::SuperHConstantPoolConstant(const GlobalVariable *GV,
-                                                 const Constant *C)
+                                                       const Constant *C)
     : SuperHConstantPoolValue((Type *)C->getType(), 0, SHCP::CPPromotedGlobal,
-                           SHCP::no_modifier), CVal(C) {
+                              SHCP::no_modifier),
+      CVal(C) {
   GVars.insert(GV);
 }
 
 SuperHConstantPoolConstant *
 SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID) {
   return new SuperHConstantPoolConstant(C, ID, SHCP::CPValue,
-                                     SHCP::no_modifier);
+                                        SHCP::no_modifier);
 }
 
 SuperHConstantPoolConstant *
 SuperHConstantPoolConstant::Create(const GlobalVariable *GVar,
-                                const Constant *Initializer) {
+                                   const Constant *Initializer) {
   return new SuperHConstantPoolConstant(GVar, Initializer);
 }
 
 SuperHConstantPoolConstant *
 SuperHConstantPoolConstant::Create(const GlobalValue *GV,
-                                SHCP::SHCPModifier Modifier) {
-  return new SuperHConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()),
-                                     GV, 0, SHCP::CPValue,
-                                     Modifier);
+                                   SHCP::SHCPModifier Modifier) {
+  return new SuperHConstantPoolConstant(
+      (Type *)Type::getInt32Ty(GV->getContext()), GV, 0, SHCP::CPValue,
+      Modifier);
 }
 
 SuperHConstantPoolConstant *
 SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID,
-                                SHCP::SHCPKind Kind) {
-  return new SuperHConstantPoolConstant(C, ID, Kind,
-                                     SHCP::no_modifier);
+                                   SHCP::SHCPKind Kind) {
+  return new SuperHConstantPoolConstant(C, ID, Kind, SHCP::no_modifier);
 }
 
 SuperHConstantPoolConstant *
 SuperHConstantPoolConstant::Create(const Constant *C, unsigned ID,
-                                SHCP::SHCPKind Kind,
-                                SHCP::SHCPModifier Modifier) {
+                                   SHCP::SHCPKind Kind,
+                                   SHCP::SHCPModifier Modifier) {
   return new SuperHConstantPoolConstant(C, ID, Kind, Modifier);
 }
 
@@ -152,12 +147,12 @@ const BlockAddress *SuperHConstantPoolConstant::getBlockAddress() const {
   return dyn_cast_or_null<BlockAddress>(CVal);
 }
 
-int SuperHConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
-                                                       Align Alignment) {
+int SuperHConstantPoolConstant::getExistingMachineCPValue(
+    MachineConstantPool *CP, Align Alignment) {
   int index =
-    getExistingMachineCPValueImpl<SuperHConstantPoolConstant>(CP, Alignment);
+      getExistingMachineCPValueImpl<SuperHConstantPoolConstant>(CP, Alignment);
   if (index != -1) {
-    auto *CPV = static_cast<SuperHConstantPoolValue*>(
+    auto *CPV = static_cast<SuperHConstantPoolValue *>(
         CP->getConstants()[index].Val.MachineCPVal);
     auto *Constant = cast<SuperHConstantPoolConstant>(CPV);
     Constant->GVars.insert_range(GVars);
@@ -166,8 +161,10 @@ int SuperHConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *C
 }
 
 bool SuperHConstantPoolConstant::hasSameValue(SuperHConstantPoolValue *ACPV) {
-  const SuperHConstantPoolConstant *ACPC = dyn_cast<SuperHConstantPoolConstant>(ACPV);
-  return ACPC && ACPC->CVal == CVal && SuperHConstantPoolValue::hasSameValue(ACPV);
+  const SuperHConstantPoolConstant *ACPC =
+      dyn_cast<SuperHConstantPoolConstant>(ACPV);
+  return ACPC && ACPC->CVal == CVal &&
+         SuperHConstantPoolValue::hasSameValue(ACPV);
 }
 
 void SuperHConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
@@ -190,23 +187,24 @@ void SuperHConstantPoolConstant::print(raw_ostream &O) const {
 //===----------------------------------------------------------------------===//
 
 SuperHConstantPoolSymbol::SuperHConstantPoolSymbol(LLVMContext &C, StringRef s,
-                                             unsigned id,
-                                             SHCP::SHCPModifier Modifier)
+                                                   unsigned id,
+                                                   SHCP::SHCPModifier Modifier)
     : SuperHConstantPoolValue(C, id, SHCP::CPExtSymbol, Modifier),
       S(std::string(s)) {}
 
-SuperHConstantPoolSymbol *SuperHConstantPoolSymbol::Create(LLVMContext &C,
-                                                     StringRef s, unsigned ID) {
+SuperHConstantPoolSymbol *
+SuperHConstantPoolSymbol::Create(LLVMContext &C, StringRef s, unsigned ID) {
   return new SuperHConstantPoolSymbol(C, s, ID, SHCP::DIR);
 }
 
 int SuperHConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
-                                                     Align Alignment) {
+                                                        Align Alignment) {
   return getExistingMachineCPValueImpl<SuperHConstantPoolSymbol>(CP, Alignment);
 }
 
 bool SuperHConstantPoolSymbol::hasSameValue(SuperHConstantPoolValue *SCPV) {
-  const SuperHConstantPoolSymbol *ACPS = dyn_cast<SuperHConstantPoolSymbol>(SCPV);
+  const SuperHConstantPoolSymbol *ACPS =
+      dyn_cast<SuperHConstantPoolSymbol>(SCPV);
   return ACPS && ACPS->S == S && SuperHConstantPoolValue::hasSameValue(SCPV);
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
index 86f718ca381ce..d5d86e4cf8104 100644
--- a/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
+++ b/llvm/lib/Target/SuperH/SuperHConstantPoolValue.h
@@ -29,28 +29,28 @@ class Type;
 
 namespace SHCP {
 
-  enum SHCPKind {
-    CPValue,
-    CPExtSymbol,
-    CPBlockAddress,
-    CPMachineBasicBlock,
-    CPPromotedGlobal
-  };
-
-  enum SHCPModifier {
-    no_modifier,  /// None
-    DIR,          /// Direct
-    GOT_PCREL,    /// Global Offset Table, PC Relative
-  };
+enum SHCPKind {
+  CPValue,
+  CPExtSymbol,
+  CPBlockAddress,
+  CPMachineBasicBlock,
+  CPPromotedGlobal
+};
+
+enum SHCPModifier {
+  no_modifier, /// None
+  DIR,         /// Direct
+  GOT_PCREL,   /// Global Offset Table, PC Relative
+};
 
 } // end namespace SHCP
 
 class SuperHConstantPoolValue : public MachineConstantPoolValue {
-  unsigned LabelId;           // Label id of the load.
-  SHCP::SHCPKind Kind;      // Kind of constant.
-  SHCP::SHCPModifier Modifier;  // GV modifier i.e. (&GV(modifier)-(LPIC+8))
+  unsigned LabelId;            // Label id of the load.
+  SHCP::SHCPKind Kind;         // Kind of constant.
+  SHCP::SHCPModifier Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8))
 protected:
-  SuperHConstantPoolValue(Type *Ty, unsigned id, SHCP::SHCPKind Kind, 
+  SuperHConstantPoolValue(Type *Ty, unsigned id, SHCP::SHCPKind Kind,
                           SHCP::SHCPModifier Modifier);
 
   SuperHConstantPoolValue(LLVMContext &C, unsigned id, SHCP::SHCPKind Kind,
@@ -62,8 +62,8 @@ class SuperHConstantPoolValue : public MachineConstantPoolValue {
     for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
       if (Constants[i].isMachineConstantPoolEntry() &&
           Constants[i].getAlign() >= Alignment) {
-        auto *CPV =
-          static_cast<SuperHConstantPoolValue*>(Constants[i].Val.MachineCPVal);
+        auto *CPV = static_cast<SuperHConstantPoolValue *>(
+            Constants[i].Val.MachineCPVal);
         if (Derived *APC = dyn_cast<Derived>(CPV))
           if (cast<Derived>(this)->equals(APC))
             return i;
@@ -86,8 +86,8 @@ class SuperHConstantPoolValue : public MachineConstantPoolValue {
   bool isGlobalValue() const { return Kind == SHCP::CPValue; }
   bool isExtSymbol() const { return Kind == SHCP::CPExtSymbol; }
   bool isBlockAddress() const { return Kind == SHCP::CPBlockAddress; }
-  bool isMachineBasicBlock() const{ return Kind == SHCP::CPMachineBasicBlock; }
-  bool isPromotedGlobal() const{ return Kind == SHCP::CPPromotedGlobal; }
+  bool isMachineBasicBlock() const { return Kind == SHCP::CPMachineBasicBlock; }
+  bool isPromotedGlobal() const { return Kind == SHCP::CPPromotedGlobal; }
 
   int getExistingMachineCPValue(MachineConstantPool *CP,
                                 Align Alignment) override;
@@ -99,48 +99,46 @@ class SuperHConstantPoolValue : public MachineConstantPoolValue {
   virtual bool hasSameValue(SuperHConstantPoolValue *ACPV);
 
   bool equals(const SuperHConstantPoolValue *A) const {
-    return this->LabelId == A->LabelId &&
-      this->Modifier == A->Modifier;
+    return this->LabelId == A->LabelId && this->Modifier == A->Modifier;
   }
 
   void print(raw_ostream &O) const override;
-  void print(raw_ostream *O) const { if (O) print(*O); }
+  void print(raw_ostream *O) const {
+    if (O)
+      print(*O);
+  }
   void dump() const;
 };
 
-inline raw_ostream &operator<<(raw_ostream &O, const SuperHConstantPoolValue &V) {
+inline raw_ostream &operator<<(raw_ostream &O,
+                               const SuperHConstantPoolValue &V) {
   V.print(O);
   return O;
 }
 
-
-/// SuperHConstantPoolConstant - SuperH-specific constant pool values for Constants,
-/// Functions, and BlockAddresses.
+/// SuperHConstantPoolConstant - SuperH-specific constant pool values for
+/// Constants, Functions, and BlockAddresses.
 class SuperHConstantPoolConstant : public SuperHConstantPoolValue {
-  const Constant *CVal;         // Constant being loaded.
-  SmallPtrSet<const GlobalVariable*, 1> GVars;
-
-  SuperHConstantPoolConstant(const Constant *C,
-                             unsigned ID,
-                             SHCP::SHCPKind Kind,
-                             SHCP::SHCPModifier Modifier);
-  SuperHConstantPoolConstant(Type *Ty, const Constant *C,
-                             unsigned ID,
-                             SHCP::SHCPKind Kind,
-                             SHCP::SHCPModifier Modifier);
+  const Constant *CVal; // Constant being loaded.
+  SmallPtrSet<const GlobalVariable *, 1> GVars;
+
+  SuperHConstantPoolConstant(const Constant *C, unsigned ID,
+                             SHCP::SHCPKind Kind, SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant(Type *Ty, const Constant *C, unsigned ID,
+                             SHCP::SHCPKind Kind, SHCP::SHCPModifier Modifier);
   SuperHConstantPoolConstant(const GlobalVariable *GV, const Constant *Init);
 
 public:
   static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID);
   static SuperHConstantPoolConstant *Create(const GlobalValue *GV,
-                                         SHCP::SHCPModifier Modifier);
+                                            SHCP::SHCPModifier Modifier);
   static SuperHConstantPoolConstant *Create(const GlobalVariable *GV,
-                                         const Constant *Initializer);
+                                            const Constant *Initializer);
   static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID,
-                                         SHCP::SHCPKind Kind);
+                                            SHCP::SHCPKind Kind);
   static SuperHConstantPoolConstant *Create(const Constant *C, unsigned ID,
-                                         SHCP::SHCPKind Kind,
-                                         SHCP::SHCPModifier Modifier);
+                                            SHCP::SHCPKind Kind,
+                                            SHCP::SHCPModifier Modifier);
 
   const GlobalValue *getGV() const;
   const BlockAddress *getBlockAddress() const;
@@ -149,9 +147,7 @@ class SuperHConstantPoolConstant : public SuperHConstantPoolValue {
 
   iterator_range<promoted_iterator> promotedGlobals() { return GVars; }
 
-  const Constant *getPromotedGlobalInit() const {
-    return CVal;
-  }
+  const Constant *getPromotedGlobalInit() const { return CVal; }
 
   int getExistingMachineCPValue(MachineConstantPool *CP,
                                 Align Alignment) override;
@@ -174,15 +170,17 @@ class SuperHConstantPoolConstant : public SuperHConstantPoolValue {
   }
 };
 
-/// SuperHConstantPoolSymbol - SH-specific constantpool 
+/// SuperHConstantPoolSymbol - SH-specific constantpool
 /// values for external symbols.
 class SuperHConstantPoolSymbol : public SuperHConstantPoolValue {
-  const std::string S;          // ExtSymbol being loaded.
+  const std::string S; // ExtSymbol being loaded.
 
-  SuperHConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id, SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id,
+                           SHCP::SHCPModifier Modifier);
 
 public:
-  static SuperHConstantPoolSymbol *Create(LLVMContext &C, StringRef s, unsigned ID);
+  static SuperHConstantPoolSymbol *Create(LLVMContext &C, StringRef s,
+                                          unsigned ID);
 
   StringRef getSymbol() const { return S; }
 
diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index 87d2f14534c51..225fb7fd7f176 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -12,12 +12,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperH.h"
 #include "SuperHInstrInfo.h"
 #include "SuperHMachineFunctionInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
-#include "MCTargetDesc/SuperHMCTargetDesc.h"
 
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -32,11 +32,11 @@ using namespace llvm;
 
 #ifndef NDEBUG
 static cl::opt<bool>
-CNoExpand("sh-no-expand", cl::Hidden, cl::init(false),
-          cl::desc("Force the backend to not expand instructions."));
+    CNoExpand("sh-no-expand", cl::Hidden, cl::init(false),
+              cl::desc("Force the backend to not expand instructions."));
 static cl::opt<bool>
-CKeepPseudo("sh-keep-pseudo", cl::Hidden, cl::init(false),
-          cl::desc("Force the backend to keep pseudos around."));
+    CKeepPseudo("sh-keep-pseudo", cl::Hidden, cl::init(false),
+                cl::desc("Force the backend to keep pseudos around."));
 #endif
 
 namespace {
@@ -76,15 +76,15 @@ class SuperHExpandPseudo : public MachineFunctionPass {
 
 // getOffsetForStackOffset - Calculates how much to offset the stack pointer for
 // the indirect load/store to be in range.
-static int64_t getOffsetForStackOffset(const MachineFunction &MF, 
-                                       uint8_t Bits, uint8_t Scale = 1) {
+static int64_t getOffsetForStackOffset(const MachineFunction &MF, uint8_t Bits,
+                                       uint8_t Scale = 1) {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  
+
   // The base value range for the instruction.
-  int64_t BM = ((1<<Bits)-1)*Scale;
+  int64_t BM = ((1 << Bits) - 1) * Scale;
   int64_t StackSize = MFI.getStackSize();
-  int64_t Slot = StackSize/BM;
-  return alignTo((BM*Slot)+(StackSize%BM), Scale);
+  int64_t Slot = StackSize / BM;
+  return alignTo((BM * Slot) + (StackSize % BM), Scale);
 }
 
 // eraseMI - Helper that erases a machine instruction while respecting
@@ -95,7 +95,7 @@ static bool eraseMI(MachineInstr &MI) {
   if (CKeepPseudo)
     return false;
 #endif
-  
+
   MI.eraseFromParent();
   return true;
 }
@@ -121,23 +121,23 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
   // Expand sequence to
   // mov      <frame reg>,  r1
   // add      #-SpOffset,   r1
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
-    .addReg(FrameReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1).addReg(FrameReg);
   BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-    .addReg(SH::R1)
-    .addImm(-SpOffset);
+      .addReg(SH::R1)
+      .addImm(-SpOffset);
 
-  switch(MI.getOpcode()) {
-  default: llvm_unreachable("Expected valid MOV*SPtr opcode.");
+  switch (MI.getOpcode()) {
+  default:
+    llvm_unreachable("Expected valid MOV*SPtr opcode.");
   case SH::MOVBSPtr: {
 
     // mov      <src reg>,  r0
     // mov.b    r0, @(offset,r1)
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
-      .addReg(SrcReg, getKillRegState(SrcIsKill));
+        .addReg(SrcReg, getKillRegState(SrcIsKill));
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS4))
-      .addReg(SH::R1, RegState::Kill)
-      .addImm(Offset);
+        .addReg(SH::R1, RegState::Kill)
+        .addImm(Offset);
     break;
   }
   case SH::MOVWSPtr: {
@@ -145,19 +145,19 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
     // mov      <src reg>,  r0
     // mov.w    r0, @(offset,r1)
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
-      .addReg(SrcReg, getKillRegState(SrcIsKill));
+        .addReg(SrcReg, getKillRegState(SrcIsKill));
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS4))
-      .addReg(SH::R1, RegState::Kill)
-      .addImm(Offset);
+        .addReg(SH::R1, RegState::Kill)
+        .addImm(Offset);
     break;
   }
   case SH::MOVLSPtr: {
 
     // mov.b    <src reg>, @(offset,r1)
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
-      .addReg(SrcReg, getKillRegState(SrcIsKill))
-      .addReg(SH::R1, RegState::Kill)
-      .addImm(Offset);
+        .addReg(SrcReg, getKillRegState(SrcIsKill))
+        .addReg(SH::R1, RegState::Kill)
+        .addImm(Offset);
     break;
   }
   }
@@ -177,30 +177,25 @@ bool SuperHExpandPseudo::storeToGlobal(Block &MBB, BlockIt MBBI) {
     return false;
 
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
-    .addConstantPoolIndex(G->getLabelId());
+      .addConstantPoolIndex(G->getLabelId());
 
-  switch(MI.getOpcode()) {
-  default: llvm_unreachable("Expected valid MOV*SPtr opcode.");
+  switch (MI.getOpcode()) {
+  default:
+    llvm_unreachable("Expected valid MOV*SPtr opcode.");
   case SH::MOVBSPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS))
-      .addReg(SrcReg)
-      .addReg(SH::R1);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS)).addReg(SrcReg).addReg(SH::R1);
     break;
   }
   case SH::MOVWSPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS))
-      .addReg(SrcReg)
-      .addReg(SH::R1);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS)).addReg(SrcReg).addReg(SH::R1);
     break;
   }
   case SH::MOVLSPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS))
-      .addReg(SrcReg)
-      .addReg(SH::R1);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS)).addReg(SrcReg).addReg(SH::R1);
     break;
   }
   }
-  
+
   return eraseMI(MI);
 }
 
@@ -261,50 +256,48 @@ bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
   // Expand sequence to
   // mov      <frame reg>,  r1
   // add      #-SpOffset,   r1
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
-    .addReg(FrameReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1).addReg(FrameReg);
   BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-    .addReg(SH::R1)
-    .addImm(-SpOffset);
+      .addReg(SH::R1)
+      .addImm(-SpOffset);
 
-  switch(MI.getOpcode()) {
-  default: llvm_unreachable("Expected valid MOV*LPtr opcode.");
+  switch (MI.getOpcode()) {
+  default:
+    llvm_unreachable("Expected valid MOV*LPtr opcode.");
   case SH::MOVBLPtr: {
 
     // mov.w    @(offset,r1), r0
     // mov      r0,           <dst reg>
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL4))
-      .addReg(SH::R1)
-      .addImm(Offset)
-      .addReg(SH::R0, RegState::Define);
+        .addReg(SH::R1)
+        .addImm(Offset)
+        .addReg(SH::R0, RegState::Define);
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
-      .addReg(DstReg, getKillRegState(DstIsKill))
-      .addReg(SH::R0, RegState::Kill);
+        .addReg(DstReg, getKillRegState(DstIsKill))
+        .addReg(SH::R0, RegState::Kill);
     break;
   }
   case SH::MOVWLPtr: {
 
     // mov.b    @(offset,r1), r0
     // mov      r0,           <dst reg>
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4))
-      .addReg(SH::R1)
-      .addImm(Offset);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4)).addReg(SH::R1).addImm(Offset);
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
-      .addReg(DstReg, getKillRegState(DstIsKill))
-      .addReg(SH::R0, RegState::Define);
+        .addReg(DstReg, getKillRegState(DstIsKill))
+        .addReg(SH::R0, RegState::Define);
     break;
   }
   case SH::MOVLLPtr: {
 
     // mov.l    @(offset,r1), <dst reg>
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4))
-      .addReg(DstReg, getKillRegState(DstIsKill))
-      .addReg(SH::R1)
-      .addImm(Offset);
+        .addReg(DstReg, getKillRegState(DstIsKill))
+        .addReg(SH::R1)
+        .addImm(Offset);
     break;
   }
   }
-  
+
   return eraseMI(MI);
 }
 
@@ -321,27 +314,25 @@ bool SuperHExpandPseudo::loadFromGlobal(Block &MBB, BlockIt MBBI) {
     return false;
 
   BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
-    .addConstantPoolIndex(G->getLabelId());
+      .addConstantPoolIndex(G->getLabelId());
 
-  switch(MI.getOpcode()) {
-  default: llvm_unreachable("Expected valid MOV*LPtr opcode.");
+  switch (MI.getOpcode()) {
+  default:
+    llvm_unreachable("Expected valid MOV*LPtr opcode.");
   case SH::MOVBLPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL), DstReg)
-      .addReg(SH::R1);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL), DstReg).addReg(SH::R1);
     break;
   }
   case SH::MOVWLPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL), DstReg)
-      .addReg(SH::R1);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL), DstReg).addReg(SH::R1);
     break;
   }
   case SH::MOVLLPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL), DstReg)
-      .addReg(SH::R1);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL), DstReg).addReg(SH::R1);
     break;
   }
   }
-  
+
   return eraseMI(MI);
 }
 
@@ -396,38 +387,34 @@ bool SuperHExpandPseudo::expand<SH::SHLri>(Block &MBB, BlockIt MBBI) {
   auto SrcReg = MI.getOperand(1).getReg();
   int64_t Offset = MI.getOperand(2).getImm();
 
-  while(Offset > 0) {
+  while (Offset > 0) {
 
     if (Offset > 16) {
-      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL16), DstReg)
-        .addReg(SrcReg);
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL16), DstReg).addReg(SrcReg);
 
       Offset -= 16;
       continue;
     }
 
     if (Offset > 8) {
-      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL8), DstReg)
-        .addReg(SrcReg);
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL8), DstReg).addReg(SrcReg);
 
       Offset -= 8;
       continue;
     }
 
     if (Offset > 2) {
-      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL2), DstReg)
-        .addReg(SrcReg);
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL2), DstReg).addReg(SrcReg);
 
       Offset -= 2;
       continue;
     }
 
-    BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL), DstReg)
-      .addReg(SrcReg);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL), DstReg).addReg(SrcReg);
     Offset -= 1;
     continue;
   }
-  
+
   return eraseMI(MI);
 }
 
@@ -442,38 +429,34 @@ bool SuperHExpandPseudo::expand<SH::SHRri>(Block &MBB, BlockIt MBBI) {
   auto SrcReg = MI.getOperand(1).getReg();
   int64_t Offset = MI.getOperand(2).getImm();
 
-  while(Offset > 0) {
-    
+  while (Offset > 0) {
+
     if (Offset > 16) {
-      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR16), DstReg)
-        .addReg(SrcReg);
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR16), DstReg).addReg(SrcReg);
 
       Offset -= 16;
       continue;
     }
 
     if (Offset > 8) {
-      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR8), DstReg)
-        .addReg(SrcReg);
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR8), DstReg).addReg(SrcReg);
 
       Offset -= 8;
       continue;
     }
 
     if (Offset > 2) {
-      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR2), DstReg)
-        .addReg(SrcReg);
+      BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR2), DstReg).addReg(SrcReg);
 
       Offset -= 2;
       continue;
     }
 
-    BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR), DstReg)
-      .addReg(SrcReg);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR), DstReg).addReg(SrcReg);
     Offset -= 1;
     continue;
   }
-  
+
   return eraseMI(MI);
 }
 
@@ -488,12 +471,11 @@ bool SuperHExpandPseudo::expand<SH::SRAri>(Block &MBB, BlockIt MBBI) {
   auto SrcReg = MI.getOperand(1).getReg();
   int64_t Offset = MI.getOperand(2).getImm();
 
-  while(Offset > 0) {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::SHAR), DstReg)
-      .addReg(SrcReg);
+  while (Offset > 0) {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::SHAR), DstReg).addReg(SrcReg);
     Offset -= 1;
   }
-  
+
   return eraseMI(MI);
 }
 
@@ -505,12 +487,9 @@ bool SuperHExpandPseudo::expand<SH::SHLrr>(Block &MBB, BlockIt MBBI) {
   auto Src1Reg = MI.getOperand(1).getReg();
   auto Src2Reg = MI.getOperand(2).getReg();
 
-  BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL))
-    .addReg(Src1Reg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::DT))
-    .addReg(Src2Reg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
-    .addImm(-4);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::SHLL)).addReg(Src1Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::DT)).addReg(Src2Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::BF)).addImm(-4);
 
   return eraseMI(MI);
 }
@@ -523,12 +502,9 @@ bool SuperHExpandPseudo::expand<SH::SHRrr>(Block &MBB, BlockIt MBBI) {
   auto Src1Reg = MI.getOperand(1).getReg();
   auto Src2Reg = MI.getOperand(2).getReg();
 
-  BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR))
-    .addReg(Src1Reg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::DT))
-    .addReg(Src2Reg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
-    .addImm(-4);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::SHLR)).addReg(Src1Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::DT)).addReg(Src2Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::BF)).addImm(-4);
 
   return eraseMI(MI);
 }
@@ -541,12 +517,9 @@ bool SuperHExpandPseudo::expand<SH::SRArr>(Block &MBB, BlockIt MBBI) {
   auto Src1Reg = MI.getOperand(1).getReg();
   auto Src2Reg = MI.getOperand(2).getReg();
 
-  BuildMI(MBB, MBBI, DL, TII->get(SH::SHAR))
-    .addReg(Src1Reg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::DT))
-    .addReg(Src2Reg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::BF))
-    .addImm(-4);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::SHAR)).addReg(Src1Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::DT)).addReg(Src2Reg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::BF)).addImm(-4);
 
   return eraseMI(MI);
 }
@@ -590,10 +563,10 @@ bool SuperHExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
   LLVM_DEBUG(dbgs() << "\n********** SuperHExpandPseudo **********\n");
   bool Modified = false;
 
-  #ifndef NDEBUG
+#ifndef NDEBUG
   if (CNoExpand)
     return false;
-  #endif
+#endif
 
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   TRI = STI.getRegisterInfo();
@@ -627,20 +600,21 @@ bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
   case Op:                                                                     \
     return expand<Op>(MBB, MI)
 
-  switch(Opcode) {
-  default: break;
-  EXPAND(SH::MOVBSPtr);
-  EXPAND(SH::MOVWSPtr);
-  EXPAND(SH::MOVLSPtr);
-  EXPAND(SH::MOVBLPtr);
-  EXPAND(SH::MOVWLPtr);
-  EXPAND(SH::MOVLLPtr);
-  EXPAND(SH::SHLri);
-  EXPAND(SH::SHRri);
-  EXPAND(SH::SRAri);
-  EXPAND(SH::SHLrr);
-  EXPAND(SH::SHRrr);
-  EXPAND(SH::SRArr);
+  switch (Opcode) {
+  default:
+    break;
+    EXPAND(SH::MOVBSPtr);
+    EXPAND(SH::MOVWSPtr);
+    EXPAND(SH::MOVLSPtr);
+    EXPAND(SH::MOVBLPtr);
+    EXPAND(SH::MOVWLPtr);
+    EXPAND(SH::MOVLLPtr);
+    EXPAND(SH::SHLri);
+    EXPAND(SH::SHRri);
+    EXPAND(SH::SRAri);
+    EXPAND(SH::SHLrr);
+    EXPAND(SH::SHRrr);
+    EXPAND(SH::SRArr);
   }
 #undef EXPAND
   return false;
@@ -650,7 +624,6 @@ char SuperHExpandPseudo::ID = 0;
 
 } // namespace
 
-
 INITIALIZE_PASS(SuperHExpandPseudo, "sh-expand-pseudo", SH_EXPAND_PSEUDO_NAME,
                 false, false)
 
diff --git a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
index a35a0a82ec252..aec81e1caeeaa 100644
--- a/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFillDelaySlots.cpp
@@ -10,10 +10,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperH.h"
 #include "SuperHInstrInfo.h"
 #include "SuperHTargetMachine.h"
-#include "MCTargetDesc/SuperHMCTargetDesc.h"
 
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
@@ -37,7 +37,9 @@ class SuperHFillDelaySlots : public MachineFunctionPass {
 
   bool runOnMachineFunction(MachineFunction &MF) override;
 
-  StringRef getPassName() const override { return SUPERH_FILL_DELAY_SLOTS_NAME; }
+  StringRef getPassName() const override {
+    return SUPERH_FILL_DELAY_SLOTS_NAME;
+  }
 
 private:
   typedef MachineBasicBlock Block;
@@ -66,7 +68,8 @@ class SuperHFillDelaySlots : public MachineFunctionPass {
 
 // Walks backwards through the basic block to find a candidate that is eligible
 // for filling delay slots.
-MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI) {
+MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB,
+                                                      BlockIt MBBI) {
   MachineInstr &MI = *MBBI;
   auto *Prev = MBBI->getPrevNode();
 
@@ -77,7 +80,8 @@ MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI)
   // // We might have a useful instruction above the instruction that
   // // loads our destination address.
   // if (MI.isCall() && Prev) {
-  //   if (!Prev->getPrevNode()->definesRegister(MI.getOperand(0).getReg(), TRI))
+  //   if (!Prev->getPrevNode()->definesRegister(MI.getOperand(0).getReg(),
+  //   TRI))
   //     Prev = Prev->getPrevNode();
   // }
 
@@ -88,13 +92,13 @@ MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI)
 
     // If we encounter a branch instruction, then it's no longer safe to
     // move the instruction down.
-    if (Prev->isBranch() || Prev->isCall() || Prev->isReturn()) 
+    if (Prev->isBranch() || Prev->isCall() || Prev->isReturn())
       return nullptr;
 
     // NOTE:  RTS has an extra constraint that it cannot have
     //        lds @r15+,PR or equivalent in its delay slot.
     if (MI.isReturn()) {
-      
+
       // Skip the LDS instruction.
       if (Opcode == SH::LDSPR || Opcode == SH::LDSMPR)
         return nullptr;
@@ -102,7 +106,7 @@ MachineInstr *SuperHFillDelaySlots::findSlotCandidate(Block &MBB, BlockIt MBBI)
 
     // NOTE:  Conditional branches can't have their condition code set
     //        in the delay slot. As such, if the previous instruction
-    //        implicitly defines the status register, assume that the 
+    //        implicitly defines the status register, assume that the
     //        T bit was set.
     if (MI.isConditionalBranch()) {
       if (Prev->definesRegister(SH::SR, TRI))
@@ -126,19 +130,20 @@ bool SuperHFillDelaySlots::fillDelaySlot(Block &MBB, BlockIt MBBI) {
   MachineInstr &MI = *MBBI;
 
   if (auto *Candidate = findSlotCandidate(MBB, MBBI)) {
-      LLVM_DEBUG(dbgs() << "Swapping " << TII->getName(MI.getOpcode()) 
-                        << " and " << TII->getName(Candidate->getOpcode()) 
-                        << " @ " << MBB.getParent()->getName() << "\n");
+    LLVM_DEBUG(dbgs() << "Swapping " << TII->getName(MI.getOpcode()) << " and "
+                      << TII->getName(Candidate->getOpcode()) << " @ "
+                      << MBB.getParent()->getName() << "\n");
 
-      MBB.insertAfter(MBBI, Candidate->removeFromParent());
-      return true;
+    MBB.insertAfter(MBBI, Candidate->removeFromParent());
+    return true;
   }
 
   LLVM_DEBUG(dbgs() << "Inserting NOP after " << TII->getName(MI.getOpcode())
                     << " @ " << MBB.getParent()->getName() << "\n");
 
   // Otherwise just insert a NOP.
-  MBB.insertAfter(MBBI, MF.CreateMachineInstr(TII->get(SH::NOP), MI.getDebugLoc())); 
+  MBB.insertAfter(MBBI,
+                  MF.CreateMachineInstr(TII->get(SH::NOP), MI.getDebugLoc()));
   return true;
 }
 
@@ -188,11 +193,10 @@ bool SuperHFillDelaySlots::runOnMachineFunction(MachineFunction &MF) {
   return Modified;
 }
 
-
 char SuperHFillDelaySlots::ID = 0;
 
-INITIALIZE_PASS(SuperHFillDelaySlots, "sh-fill-delay-slots", SUPERH_FILL_DELAY_SLOTS_NAME,
-                false, false)
+INITIALIZE_PASS(SuperHFillDelaySlots, "sh-fill-delay-slots",
+                SUPERH_FILL_DELAY_SLOTS_NAME, false, false)
 
 FunctionPass *llvm::createSuperHFillDelaySlotsPass() {
   return new SuperHFillDelaySlots();
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index d275c40055e5b..86a923fb9c48d 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -11,7 +11,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-
 #include "SuperHFrameLowering.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperHInstrInfo.h"
@@ -39,9 +38,9 @@
 
 #define DEBUG_TYPE "sh-framelowering"
 
-static cl::opt<bool>
-AccumOutgoingArgs("sh-accumulate-outgoing-args", cl::Hidden, cl::init(false),
-          cl::desc("Reserve space for outgoing arguments in the function prologue."));
+static cl::opt<bool> AccumOutgoingArgs(
+    "sh-accumulate-outgoing-args", cl::Hidden, cl::init(false),
+    cl::desc("Reserve space for outgoing arguments in the function prologue."));
 
 using namespace llvm;
 
@@ -56,20 +55,24 @@ using namespace llvm;
 // for it to fit.
 static unsigned getShiftAmt(uint32_t Val) {
   unsigned R = 0;
-  for(unsigned i = 0; i < 4; i++) {
-    if (((Val >> (i*8)) & 0xFF))
+  for (unsigned i = 0; i < 4; i++) {
+    if (((Val >> (i * 8)) & 0xFF))
       R = i;
   }
   return R;
 }
 
 // Helper to emit stack pointer adjustment.
-void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB, 
-                                          MachineBasicBlock::iterator MBBI, int32_t AdjValue) const {
-  const SuperHInstrInfo &TII = *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
-  MachineInstr::MIFlag MFlag = AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
+void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF,
+                                          MachineBasicBlock &MBB,
+                                          MachineBasicBlock::iterator MBBI,
+                                          int32_t AdjValue) const {
+  const SuperHInstrInfo &TII =
+      *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
+  MachineInstr::MIFlag MFlag =
+      AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
-  
+
   // No stack frame allocation neccesary.
   if (AdjValue == 0)
     return;
@@ -79,8 +82,8 @@ void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, Ma
 
     // Fast path, emit a single immediate add.
     BuildMI(MBB, MBBI, DL, TII.get(SH::ADDI), Base)
-      .addReg(Base)
-      .addImm(AdjValue);
+        .addReg(Base)
+        .addImm(AdjValue);
     return;
   }
 
@@ -91,19 +94,19 @@ void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, Ma
 
   // Empty R0 in case it had something.
   BuildMI(MBB, MBBI, DL, TII.get(SH::XOR), SH::R0)
-    .addReg(SH::R0)
-    .setMIFlag(MFlag);
+      .addReg(SH::R0)
+      .setMIFlag(MFlag);
 
   // Shift value in with the following pattern:
   //  or #(byte), r0
   //  shll8 r0
-  for(unsigned i = 0; i < ToShift; i++) {
+  for (unsigned i = 0; i < ToShift; i++) {
     BuildMI(MBB, MBBI, DL, TII.get(SH::ORI))
-      .addImm((AdjValue >> (i*8)) & 0xFF)
-      .setMIFlag(MFlag);
+        .addImm((AdjValue >> (i * 8)) & 0xFF)
+        .setMIFlag(MFlag);
     BuildMI(MBB, MBBI, DL, TII.get(SH::SHLL8), SH::R0)
-      .addReg(SH::R0)
-      .setMIFlag(MFlag);
+        .addReg(SH::R0)
+        .setMIFlag(MFlag);
   }
 
   // Finally negate and add to r15.
@@ -111,14 +114,14 @@ void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, Ma
   //  add r0, <base>
   if (AdjValue < 0)
     BuildMI(MBB, MBBI, DL, TII.get(SH::NEG), SH::R0)
-      .addReg(SH::R0)
-      .addReg(SH::R0)
-      .setMIFlag(MFlag);
+        .addReg(SH::R0)
+        .addReg(SH::R0)
+        .setMIFlag(MFlag);
 
   BuildMI(MBB, MBBI, DL, TII.get(SH::SUB), Base)
-    .addReg(SH::R0, RegState::Kill)
-    .addReg(Base)
-    .setMIFlag(MFlag);
+      .addReg(SH::R0, RegState::Kill)
+      .addReg(Base)
+      .setMIFlag(MFlag);
 }
 
 
@@ -130,7 +133,7 @@ void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF, Ma
 
 StackOffset
 SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
-                                           Register &FrameReg) const {
+                                            Register &FrameReg) const {
   const SuperHSubtarget &Subtarget = MF.getSubtarget<SuperHSubtarget>();
   const SuperHRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -160,7 +163,8 @@ SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
 //                          Prologue/Epilogue Emission
 //===--------------------------------------------------------------------------===//
 
-void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+void SuperHFrameLowering::emitPrologue(MachineFunction &MF,
+                                       MachineBasicBlock &MBB) const {
   LLVM_DEBUG(dbgs() << "Emitting prologue for " << MF.getName() << "...\n");
 
   MachineBasicBlock::iterator MBBI = MBB.begin();
@@ -185,23 +189,23 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
   // Store previous frame pointer.
   if (HasFP) {
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLM), FP)
-      .addReg(SP)
-      .setMIFlag(MachineInstr::FrameSetup);
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameSetup);
   }
 
   // Store Return address on stack (if needed)
   if (MFI.hasCalls()) {
     BuildMI(MBB, MBBI, DL, TII.get(SH::STSMPR))
-      .addReg(SP)
-      .setMIFlag(MachineInstr::FrameSetup);
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameSetup);
   }
 
   // Create new stack frame.
   emitFrameAdjust(SP, MF, MBB, MBBI, -StackSize);
   if (HasFP) {
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), FP)
-      .addReg(SP)
-      .setMIFlag(MachineInstr::FrameSetup);
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameSetup);
   }
 
   // // Store GOT
@@ -214,7 +218,8 @@ void SuperHFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &M
   // }
 }
 
-void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
+void SuperHFrameLowering::emitEpilogue(MachineFunction &MF,
+                                       MachineBasicBlock &MBB) const {
   LLVM_DEBUG(dbgs() << "Emitting epilogue for " << MF.getName() << "...\n");
 
   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
@@ -227,7 +232,6 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
   bool HasFP = hasFP(MF);
 
-
   // Get stack frame size.
   int64_t StackSize = MFI.getStackSize();
 
@@ -235,24 +239,24 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
   if (HasFP) {
     emitFrameAdjust(FP, MF, MBB, MBBI, StackSize);
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOV), SP)
-      .addReg(FP)
-      .setMIFlag(MachineInstr::FrameSetup);
+        .addReg(FP)
+        .setMIFlag(MachineInstr::FrameSetup);
   } else {
     emitFrameAdjust(SP, MF, MBB, MBBI, StackSize);
   }
 
   // Restore return address from stack (if needed.)
-  if (MFI.hasCalls()) { 
+  if (MFI.hasCalls()) {
     BuildMI(MBB, MBBI, DL, TII.get(SH::LDSMPR))
-      .addReg(SP)
-      .setMIFlag(MachineInstr::FrameDestroy);
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameDestroy);
   }
 
   // Restore stack pointer
   if (HasFP) {
     BuildMI(MBB, MBBI, DL, TII.get(SH::MOVLP), FP)
-      .addReg(SP)
-      .setMIFlag(MachineInstr::FrameDestroy);
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameDestroy);
   }
 
   // TODO: Handle GOT
@@ -265,14 +269,16 @@ void SuperHFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &M
 //                                Callee-Saves
 //===--------------------------------------------------------------------------===//
 
-void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
-                        RegScavenger *RS) const {
+void SuperHFrameLowering::determineCalleeSaves(MachineFunction &MF,
+                                               BitVector &SavedRegs,
+                                               RegScavenger *RS) const {
   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 }
 
-bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
-                                 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
-  
+bool SuperHFrameLowering::spillCalleeSavedRegisters(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+    ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+
   LLVM_DEBUG(dbgs() << "Spilling " << CSI.size() << " registers...\n");
   if (CSI.empty()) {
     return false;
@@ -283,17 +289,19 @@ bool SuperHFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, Mach
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   const TargetInstrInfo &TII = *STI.getInstrInfo();
   for (const CalleeSavedInfo &I : reverse(CSI)) {
-    TII.storeRegToStackSlot(MBB, MI, I.getReg(), true, I.getFrameIdx(), &SH::GPRRegClass, 0);
+    TII.storeRegToStackSlot(MBB, MI, I.getReg(), true, I.getFrameIdx(),
+                            &SH::GPRRegClass, 0);
   }
   return true;
 }
 
-bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator II,
-                                   MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
-  
+bool SuperHFrameLowering::restoreCalleeSavedRegisters(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator II,
+    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+
   LLVM_DEBUG(dbgs() << "Restoring " << CSI.size() << " registers...\n");
   if (CSI.empty()) {
-      return false;
+    return false;
   }
 
   DebugLoc DL = MBB.findDebugLoc(II);
@@ -301,7 +309,8 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   const TargetInstrInfo &TII = *STI.getInstrInfo();
   for (const CalleeSavedInfo &I : CSI) {
-    TII.loadRegFromStackSlot(MBB, II, I.getReg(), I.getFrameIdx(), &SH::GPRRegClass, 0);
+    TII.loadRegFromStackSlot(MBB, II, I.getReg(), I.getFrameIdx(),
+                             &SH::GPRRegClass, 0);
   }
 
   return true;
@@ -314,10 +323,9 @@ bool SuperHFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, Ma
 //                               Call-Frame Meta
 //===--------------------------------------------------------------------------===//
 
-MachineBasicBlock::iterator
-SuperHFrameLowering::eliminateCallFramePseudoInstr(MachineFunction &MF, 
-                            MachineBasicBlock &MBB,
-                            MachineBasicBlock::iterator MI) const {
+MachineBasicBlock::iterator SuperHFrameLowering::eliminateCallFramePseudoInstr(
+    MachineFunction &MF, MachineBasicBlock &MBB,
+    MachineBasicBlock::iterator MI) const {
   const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
   const SuperHInstrInfo &TII = *STI.getInstrInfo();
 
@@ -344,11 +352,12 @@ bool SuperHFrameLowering::canSimplifyCallFramePseudos(
 
 bool SuperHFrameLowering::hasFPImpl(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  return MF.disableFramePointerElim() ||
-         MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken();
+  return MF.disableFramePointerElim() || MFI.hasVarSizedObjects() ||
+         MFI.isFrameAddressTaken();
 }
 
-bool SuperHFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
+bool SuperHFrameLowering::hasReservedCallFrame(
+    const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   return hasFP(MF) && !MFI.hasVarSizedObjects();
 }
@@ -379,8 +388,8 @@ struct SuperHFrameFixupPass : public MachineFunctionPass {
 
   SuperHFrameFixupPass() : MachineFunctionPass(ID) {}
 
-  // Fixes up JSR instructions so that their return values don't 
-  // get clobbered by the implicit uses of R0 and R1 done by stack 
+  // Fixes up JSR instructions so that their return values don't
+  // get clobbered by the implicit uses of R0 and R1 done by stack
   // loads.
   bool fixupJSR(Block MBB, BlockIt MBII) {
     LLVM_DEBUG(dbgs() << " - Fixing up JSR instruction...\n");
@@ -391,7 +400,7 @@ struct SuperHFrameFixupPass : public MachineFunctionPass {
     while (II != E) {
       BlockIt NII = std::next(II);
 
-      switch(II->getOpcode()) {
+      switch (II->getOpcode()) {
       case SH::MOVBLPtr:
       case SH::MOVWLPtr:
       case SH::MOVLLPtr:
@@ -400,16 +409,17 @@ struct SuperHFrameFixupPass : public MachineFunctionPass {
         break;
       }
       case SH::COPY: {
-        if (II->readsRegister(SH::R0, nullptr) || II->readsRegister(SH::R1, nullptr)) {
+        if (II->readsRegister(SH::R0, nullptr) ||
+            II->readsRegister(SH::R1, nullptr)) {
           II->moveBefore(MP);
           Moved++;
         }
         break;
       }
-      default: 
+      default:
 
-        // We've reached a barrier where moving instructions up could be dangerous.
-        // as such, end the MBB pass here.
+        // We've reached a barrier where moving instructions up could be
+        // dangerous. as such, end the MBB pass here.
         NII = E;
         break;
       }
@@ -424,8 +434,9 @@ struct SuperHFrameFixupPass : public MachineFunctionPass {
   bool runOnBasicBlock(Block &MBB) {
     BlockIt II = MBB.begin(), E = MBB.end();
     while (II != E) {
-      switch(II->getOpcode()) {
-      default: break;
+      switch (II->getOpcode()) {
+      default:
+        break;
       case SH::JSR:
         return fixupJSR(MBB, II);
       }
@@ -444,17 +455,21 @@ struct SuperHFrameFixupPass : public MachineFunctionPass {
     for (Block &BB : MF) {
       Modified += runOnBasicBlock(BB);
     }
-    LLVM_DEBUG(dbgs() << "Modified " << Modified << " BBs in " << MF.getName() << "...\n\n");
+    LLVM_DEBUG(dbgs() << "Modified " << Modified << " BBs in " << MF.getName()
+                      << "...\n\n");
     return Modified > 0;
   }
 
-
-  StringRef getPassName() const override { return "SuperH frame load/store fixup pass"; }
+  StringRef getPassName() const override {
+    return "SuperH frame load/store fixup pass";
+  }
 };
 
 char SuperHFrameFixupPass::ID = 0;
 
 /// Creates instance of the frame analyzer pass.
-FunctionPass *createSuperHFrameFixupPass() { return new SuperHFrameFixupPass(); }
+FunctionPass *createSuperHFrameFixupPass() {
+  return new SuperHFrameFixupPass();
+}
 
 } // namespace llvm
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.h b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
index 10a8f8ac65b85..66f2b19d9cf74 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.h
@@ -26,26 +26,33 @@ class SuperHFrameLowering : public TargetFrameLowering {
 
 public:
   explicit SuperHFrameLowering(const SuperHSubtarget &STI)
-    : TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
-                          /*StackAlignment*/Align(4),
-                          /*LocalAreaOffset*/0,
-                          /*TransAl*/Align(1),
-                          /*StackReal*/false),
-      STI(STI) {}
+      : TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
+                            /*StackAlignment*/ Align(4),
+                            /*LocalAreaOffset*/ 0,
+                            /*TransAl*/ Align(1),
+                            /*StackReal*/ false),
+        STI(STI) {}
   bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;
   bool hasReservedCallFrame(const MachineFunction &MF) const override;
 
   void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
   void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
-  bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
-                                 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
-  bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
-                                   MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const override;
+  bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+                                 MachineBasicBlock::iterator MI,
+                                 ArrayRef<CalleeSavedInfo> CSI,
+                                 const TargetRegisterInfo *TRI) const override;
+  bool
+  restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MI,
+                              MutableArrayRef<CalleeSavedInfo> CSI,
+                              const TargetRegisterInfo *TRI) const override;
 
   void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
                             RegScavenger *RS) const override;
 
-  void emitFrameAdjust(Register Base, MachineFunction &MF, MachineBasicBlock &MBB,  MachineBasicBlock::iterator MBBI, int32_t AdjValue) const;
+  void emitFrameAdjust(Register Base, MachineFunction &MF,
+                       MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+                       int32_t AdjValue) const;
 
   /// getFrameIndexReference - This method should return the base register
   /// and offset used to reference a frame index location. The offset is
@@ -56,11 +63,11 @@ class SuperHFrameLowering : public TargetFrameLowering {
   MachineBasicBlock::iterator
   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
                                 MachineBasicBlock::iterator I) const override;
+
 protected:
   bool hasFPImpl(const MachineFunction &MF) 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/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index b3fff5b4d8de6..070e9ca6ceec1 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -17,9 +17,9 @@
 #include "SuperHConstantPoolValue.h"
 #include "SuperHInstrInfo.h"
 #include "SuperHMachineFunctionInfo.h"
+#include "SuperHSelectionDAGInfo.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"
@@ -31,9 +31,9 @@
 #define DEBUG_TYPE "sh-isel"
 #define PASS_NAME "SH DAG->DAG Instruction Selection"
 
-static cl::opt<bool>
-CBranchForceDelaySlot("sh-cbranch-force-delay-slot", cl::Hidden, cl::init(false),
-          cl::desc("Force the usage of delay slots for conditional branches."));
+static cl::opt<bool> CBranchForceDelaySlot(
+    "sh-cbranch-force-delay-slot", cl::Hidden, cl::init(false),
+    cl::desc("Force the usage of delay slots for conditional branches."));
 
 using namespace llvm;
 
@@ -51,22 +51,19 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
   bool SelectInlineAsmMemoryOperand(const SDValue &Op,
                                     InlineAsm::ConstraintCode ConstraintCode,
                                     std::vector<SDValue> &OutOps) override;
-  
-  bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
 
+  bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
 
   /// Return a target constant with the specified value of type i4.
   inline SDValue getI4Imm(int64_t Imm, const SDLoc &DL) {
     return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i4);
   }
 
-
   /// Return a target constant with the specified value of type i8.
   inline SDValue getI8Imm(int64_t Imm, const SDLoc &DL) {
     return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i8);
   }
 
-
   /// Return a target constant with the specified value of type i16.
   inline SDValue getI16Imm(int64_t Imm, const SDLoc &DL) {
     return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i16);
@@ -80,8 +77,7 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
 
   bool trySelect(SDNode *N);
 
-  template<unsigned Opcode>
-  bool trySelect(SDNode *N);
+  template <unsigned Opcode> bool trySelect(SDNode *N);
 
   const SuperHSubtarget *Subtarget;
 };
@@ -89,8 +85,10 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
 class SuperHDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
 public:
   static char ID;
-  explicit SuperHDAGToDAGISelLegacy(SuperHTargetMachine &TM, CodeGenOptLevel OptLevel)
-      : SelectionDAGISelLegacy(ID, std::make_unique<SuperHDAGToDAGISel>(TM, OptLevel)) {}
+  explicit SuperHDAGToDAGISelLegacy(SuperHTargetMachine &TM,
+                                    CodeGenOptLevel OptLevel)
+      : SelectionDAGISelLegacy(
+            ID, std::make_unique<SuperHDAGToDAGISel>(TM, OptLevel)) {}
 };
 } // end anonymous namespace
 
@@ -103,9 +101,9 @@ bool SuperHDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
   return SelectionDAGISel::runOnMachineFunction(MF);
 }
 
-bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
-                                    InlineAsm::ConstraintCode ConstraintCode,
-                                    std::vector<SDValue> &OutOps) {
+bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(
+    const SDValue &Op, InlineAsm::ConstraintCode ConstraintCode,
+    std::vector<SDValue> &OutOps) {
   return false;
 }
 
@@ -136,7 +134,8 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
     // Handle reg + offset
     if (N.getOpcode() == ISD::ADD) {
       Base = N.getOperand(0);
-      Disp = CurDAG->getTargetConstant(RHS->getZExtValue(), SDLoc(Op), MVT::i32);
+      Disp =
+          CurDAG->getTargetConstant(RHS->getZExtValue(), SDLoc(Op), MVT::i32);
       return true;
     }
   }
@@ -157,8 +156,7 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
 //                             Address Lowering
 //===----------------------------------------------------------------------===//
 
-template<>
-bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
+template <> bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
   auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
   auto DL = SDLoc(N);
 
@@ -167,7 +165,8 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
   SDValue N0 = N->getOperand(0);
 
   // External Symbols
-  if (ExternalSymbolSDNode* Sym = dyn_cast<ExternalSymbolSDNode>(N0.getNode())) {
+  if (ExternalSymbolSDNode *Sym =
+          dyn_cast<ExternalSymbolSDNode>(N0.getNode())) {
     if (auto *CPV = SFI->tryGetConstant(Sym, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
@@ -177,7 +176,7 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
   }
 
   // Block Addresses
-  if (BlockAddressSDNode* BA = dyn_cast<BlockAddressSDNode>(N0.getNode())) {
+  if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(N0.getNode())) {
     if (auto *CPV = SFI->tryGetConstant(BA, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
@@ -186,7 +185,7 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
     }
   }
 
-  if (ConstantSDNode* Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
+  if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
     if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
@@ -196,7 +195,7 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
   }
 
   // Global Addresses
-  if (GlobalAddressSDNode* GA = dyn_cast<GlobalAddressSDNode>(N0.getNode())) {
+  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N0.getNode())) {
     if (auto *CPV = SFI->tryGetConstant(GA, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
@@ -214,18 +213,19 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
 //                          Conditionals Lowering
 //===----------------------------------------------------------------------===//
 
-template<>
-bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
+template <> bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
   SDValue LHS = N->getOperand(0);
   SDValue RHS = N->getOperand(1);
-  SHCC::CondCode CC = (SHCC::CondCode)dyn_cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
+  SHCC::CondCode CC = (SHCC::CondCode)dyn_cast<ConstantSDNode>(N->getOperand(2))
+                          ->getZExtValue();
   SDLoc DL(N);
 
   // NOTE:  The comparisons just set the T bit, it's up to later instructions
   //        to interpret the T bit as positive or negative.
   SDNode *Res = nullptr;
-  switch(CC) {
-  default: break;
+  switch (CC) {
+  default:
+    break;
   case SHCC::COND_EQ: {
 
     // TST would be faster in this case.
@@ -273,26 +273,27 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
   return false;
 }
 
-template<>
-bool SuperHDAGToDAGISel::trySelect<SHISD::BRCOND>(SDNode *N) {
+template <> bool SuperHDAGToDAGISel::trySelect<SHISD::BRCOND>(SDNode *N) {
   SDValue Chain = N->getOperand(0);
   SDValue Dest = N->getOperand(1);
-  SHCC::CondCode CC = (SHCC::CondCode)dyn_cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
+  SHCC::CondCode CC = (SHCC::CondCode)dyn_cast<ConstantSDNode>(N->getOperand(2))
+                          ->getZExtValue();
   SDValue Cmp = N->getOperand(3);
   SDLoc DL(N);
 
   // NOTE:  The comparisons just set the T bit, it's up to later instructions
   //        to interpret the T bit as positive or negative.
   MachineSDNode *Res = nullptr;
-  switch(CC) {
-  default: break;
+  switch (CC) {
+  default:
+    break;
   case SHCC::COND_T:
-    Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BTS : SH::BT, 
-          DL, MVT::Other, Dest, Chain, Cmp);
+    Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BTS : SH::BT, DL,
+                                 MVT::Other, Dest, Chain, Cmp);
     break;
   case SHCC::COND_F:
-    Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BFS : SH::BF, 
-          DL, MVT::Other, Dest, Chain, Cmp);
+    Res = CurDAG->getMachineNode(CBranchForceDelaySlot ? SH::BFS : SH::BF, DL,
+                                 MVT::Other, Dest, Chain, Cmp);
     break;
   }
 
@@ -312,13 +313,13 @@ bool SuperHDAGToDAGISel::trySelect<SHISD::BRCOND>(SDNode *N) {
 //                             Branch Lowering
 //===----------------------------------------------------------------------===//
 
-template<>
-bool SuperHDAGToDAGISel::trySelect<ISD::FrameIndex>(SDNode *N) {
+template <> bool SuperHDAGToDAGISel::trySelect<ISD::FrameIndex>(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));
+  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;
@@ -339,21 +340,21 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
   case Op:                                                                     \
     return trySelect<Op>(N)
 
-  switch(Opcode) {
-  default: break;
+  switch (Opcode) {
+  default:
+    break;
   case ISD::GLOBAL_OFFSET_TABLE: {
-    SDValue GOT = CurDAG->getTargetExternalSymbol(
-        "_GLOBAL_OFFSET_TABLE_", MVT::i32, SHII::MO_GOTPC);
-    MachineSDNode *Res = 
-        CurDAG->getMachineNode(SH::MOVA, DL, MVT::i32, GOT);
+    SDValue GOT = CurDAG->getTargetExternalSymbol("_GLOBAL_OFFSET_TABLE_",
+                                                  MVT::i32, SHII::MO_GOTPC);
+    MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVA, DL, MVT::i32, GOT);
     ReplaceNode(N, Res);
     return true;
   }
 
-  SELECT(ISD::FrameIndex);
-  SELECT(SHISD::WRAPPER);
-  SELECT(SHISD::BRCOND);
-  SELECT(SHISD::CMP);
+    SELECT(ISD::FrameIndex);
+    SELECT(SHISD::WRAPPER);
+    SELECT(SHISD::BRCOND);
+    SELECT(SHISD::CMP);
   }
 
 #undef SELECT
@@ -363,7 +364,7 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
 void SuperHDAGToDAGISel::Select(SDNode *N) {
 
   LLVM_DEBUG(dbgs() << "SH: Selecting "; N->dump(CurDAG); dbgs() << '\n');
-  
+
   // Node was already selected?
   if (N->isMachineOpcode()) {
     LLVM_DEBUG(dbgs() << "== "; N->dump(CurDAG); dbgs() << '\n');
@@ -380,6 +381,6 @@ void SuperHDAGToDAGISel::Select(SDNode *N) {
 }
 
 FunctionPass *llvm::createSuperHISelDag(SuperHTargetMachine &TM,
-                                     CodeGenOptLevel OptLevel) {
+                                        CodeGenOptLevel OptLevel) {
   return new SuperHDAGToDAGISelLegacy(TM, OptLevel);
 }
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 3035002d92e85..cc0cfff092cb3 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -12,13 +12,13 @@
 //===-----------------------------------------------------------------------===//
 
 #include "SuperHISelLowering.h"
+#include "MCTargetDesc/SuperHBaseInfo.h"
+#include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperHConstantPoolValue.h"
 #include "SuperHInstrInfo.h"
 #include "SuperHMachineFunctionInfo.h"
-#include "SuperHSelectionDAGInfo.h"
-#include "MCTargetDesc/SuperHMCTargetDesc.h"
-#include "MCTargetDesc/SuperHBaseInfo.h"
 #include "SuperHRegisterInfo.h"
+#include "SuperHSelectionDAGInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -41,8 +41,8 @@ using namespace llvm;
 
 #define DEBUG_TYPE "sh-lower"
 
-#define DEBUG_FN_PRINT() LLVM_DEBUG(dbgs() << " - " << __PRETTY_FUNCTION__ << "\n");
-
+#define DEBUG_FN_PRINT()                                                       \
+  LLVM_DEBUG(dbgs() << " - " << __PRETTY_FUNCTION__ << "\n");
 
 SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
                                            const SuperHSubtarget &STI)
@@ -89,7 +89,7 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
   setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
-  
+
   for (MVT VT : MVT::integer_valuetypes()) {
     setOperationAction(ISD::Constant, VT, Custom);
   }
@@ -126,14 +126,12 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
 //===----------------------------------------------------------------------===//
 
 static bool RetCC_SH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
-                               CCValAssign::LocInfo &LocInfo,
-                               ISD::ArgFlagsTy &ArgFlags, CCState &State) {
-  assert (ArgFlags.isSRet());
+                          CCValAssign::LocInfo &LocInfo,
+                          ISD::ArgFlagsTy &ArgFlags, CCState &State) {
+  assert(ArgFlags.isSRet());
 
   // Assign SRet argument.
-  State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
-                                         0,
-                                         LocVT, LocInfo));
+  State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 0, LocVT, LocInfo));
   return true;
 }
 
@@ -155,15 +153,16 @@ static bool RetCC_SH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 //===----------------------------------------------------------------------===//
 //                        CONDITIONAL BRANCH LOWERING
 //===----------------------------------------------------------------------===//
-SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
-                                       SDValue &OutCC, SelectionDAG &DAG, 
-                                       SDLoc DL) const {
+SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
+                                       ISD::CondCode CC, SDValue &OutCC,
+                                       SelectionDAG &DAG, SDLoc DL) const {
   SDValue InCC;
   SHCC::CondCode SHcc = SHCC::COND_INVALID;
   SHCC::CondCode SHocc = SHCC::COND_T;
 
-  switch(CC) {
-  default: break;
+  switch (CC) {
+  default:
+    break;
   case ISD::SETEQ: {
     SHcc = SHCC::COND_EQ;
     SHocc = SHCC::COND_T;
@@ -241,7 +240,8 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode C
   return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, InCC);
 }
 
-SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
+SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op,
+                                             SelectionDAG &DAG) const {
   SDValue LHS = Op.getOperand(0);
   SDValue RHS = Op.getOperand(1);
   SDValue TrueV = Op.getOperand(2);
@@ -296,9 +296,9 @@ SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
 //                              TYPE LOWERING
 //===----------------------------------------------------------------------===//
 
-void 
-SuperHTargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, 
-                                         SelectionDAG &DAG) const {
+void SuperHTargetLowering::ReplaceNodeResults(SDNode *N,
+                                              SmallVectorImpl<SDValue> &Results,
+                                              SelectionDAG &DAG) const {
   DEBUG_FN_PRINT()
 
   SDLoc DL(N);
@@ -328,7 +328,8 @@ SuperHTargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Re
 //                            CONSTANT LOWERING
 //===----------------------------------------------------------------------===//
 
-SDValue SuperHTargetLowering::LowerConstant(SDValue Op, SelectionDAG &DAG) const {
+SDValue SuperHTargetLowering::LowerConstant(SDValue Op,
+                                            SelectionDAG &DAG) const {
   DEBUG_FN_PRINT()
 
   // Get the address of the target into a register
@@ -341,7 +342,8 @@ SDValue SuperHTargetLowering::LowerConstant(SDValue Op, SelectionDAG &DAG) const
     }
 
     // Constant would NOT fit in immediate, lower to constpool.
-    SDValue Const = DAG.getSignedTargetConstant(C->getSExtValue(), DL, C->getValueType(0));
+    SDValue Const =
+        DAG.getSignedTargetConstant(C->getSExtValue(), DL, C->getValueType(0));
     return DAG.getNode(SHISD::WRAPPER, DL, C->getValueType(0), Const);
   }
   return SDValue();
@@ -354,7 +356,8 @@ SDValue SuperHTargetLowering::LowerConstant(SDValue Op, SelectionDAG &DAG) const
 //                             ADDRESS LOWERING
 //===----------------------------------------------------------------------===//
 
-SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const {
+SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op,
+                                                 SelectionDAG &DAG) const {
   DEBUG_FN_PRINT()
 
   // Get the address of the target into a register
@@ -363,13 +366,15 @@ SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
     auto DL = SDLoc(G);
 
     SHRefClass OpFlags = Subtarget->classifyGlobalReference(G->getGlobal());
-    SDValue Addr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, OpFlags);
+    SDValue Addr =
+        DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, OpFlags);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
   }
   return SDValue();
 }
 
-SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const {
+SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op,
+                                                  SelectionDAG &DAG) const {
   DEBUG_FN_PRINT()
 
   // Get the address of the target into a register
@@ -378,7 +383,8 @@ SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG)
     auto DL = SDLoc(S);
 
     const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
-    SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
+    SHRefClass OpFlags =
+        Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
 
     SDValue Addr = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
@@ -386,7 +392,8 @@ SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG)
   return SDValue();
 }
 
-SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
+SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op,
+                                                SelectionDAG &DAG) const {
   DEBUG_FN_PRINT()
 
   // Get the address of the target into a register
@@ -395,9 +402,11 @@ SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) c
     auto DL = SDLoc(BA);
 
     const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
-    SHRefClass OpFlags = Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
+    SHRefClass OpFlags =
+        Subtarget->classifyGlobalFunctionReference(nullptr, *Mod);
 
-    SDValue Addr = DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT, 0, OpFlags);
+    SDValue Addr =
+        DAG.getTargetBlockAddress(BA->getBlockAddress(), PtrVT, 0, OpFlags);
     return DAG.getNode(SHISD::WRAPPER, DL, MVT::i32, Addr);
   }
   return SDValue();
@@ -410,19 +419,18 @@ SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) c
 //                             ARGUMENT LOWERING
 //===----------------------------------------------------------------------===//
 
-
-SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
-                       CallingConv::ID CallConv, bool IsVarArg,
-                       const SmallVectorImpl<ISD::InputArg> &Ins,
-                       const SDLoc &dl, SelectionDAG &DAG,
-                       SmallVectorImpl<SDValue> &InVals) const {
+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();
   DataLayout DL = DAG.getDataLayout();
 
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   SmallVector<CCValAssign, 16> ArgLocs;
-  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext());
+  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
+                 *DAG.getContext());
   CCInfo.AnalyzeFormalArguments(Ins, CC_SH);
 
   SDValue ArgValue;
@@ -482,7 +490,7 @@ SDValue SuperHTargetLowering::LowerFormalArguments(SDValue Chain,
       // Create the SelectionDAG nodes corresponding to a load
       // from this parameter.
       SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DL));
-      ArgValue = DAG.getLoad(LocVT, dl, Chain, FIN, 
+      ArgValue = DAG.getLoad(LocVT, dl, Chain, FIN,
                              MachinePointerInfo::getFixedStack(MF, FI));
     }
 
@@ -518,15 +526,16 @@ bool SuperHTargetLowering::CanLowerReturn(
   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 {
-  
+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());
+                 *DAG.getContext());
 
   // Analyze return values.
   MachineFunction &MF = DAG.getMachineFunction();
@@ -549,14 +558,16 @@ SDValue SuperHTargetLowering::LowerReturn(SDValue Chain,
   }
 
   // Update chain.
-  RetOps[0] = Chain; 
+  RetOps[0] = Chain;
   if (Glue.getNode())
     RetOps.push_back(Glue);
 
   return DAG.getNode(SHISD::RET_GLUE, dl, MVT::Other, RetOps);
 }
 
-SDValue SuperHTargetLowering::getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const {
+SDValue
+SuperHTargetLowering::getPICJumpTableRelocBase(SDValue Table,
+                                               SelectionDAG &DAG) const {
   return DAG.getRegister(Subtarget->getRegisterInfo()->getGOTRegister(),
                          getPointerTy(DAG.getDataLayout()));
 }
@@ -569,7 +580,9 @@ SDValue SuperHTargetLowering::getPICJumpTableRelocBase(SDValue Table, SelectionD
 //                              CALL LOWERING
 //===----------------------------------------------------------------------===//
 
-SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const {
+SDValue
+SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI,
+                                SmallVectorImpl<SDValue> &InVals) const {
   const SuperHRegisterInfo &RI = *Subtarget->getRegisterInfo();
   SelectionDAG &DAG = CLI.DAG;
   MachineFunction &MF = DAG.getMachineFunction();
@@ -583,8 +596,8 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
   CallingConv::ID CallConv = CLI.CallConv;
   bool IsVarArg = CLI.IsVarArg;
 
-  // TODO: This was all yoinked from AVR, it likely needs to be modified to fit the calling
-  // convention of SuperH.
+  // TODO: This was all yoinked from AVR, it likely needs to be modified to fit
+  // the calling convention of SuperH.
 
   // Tail Call Optimisation not supported yet.
   IsTailCall = false;
@@ -729,7 +742,8 @@ SDValue SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVectorImpl<S
   Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
   InGlue = Chain.getValue(1);
 
-  return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG, InVals);
+  return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
+                         InVals);
 }
 
 SDValue SuperHTargetLowering::LowerCallResult(
@@ -827,7 +841,6 @@ SDValue SuperHTargetLowering::LowerDIV(SDValue Op, SelectionDAG &DAG) const {
 
   Type *RetTy = (Type *)StructType::get(Ty, Ty);
 
-
   SDLoc dl(Op);
   TargetLowering::CallLoweringInfo CLI(DAG);
   CLI.setDebugLoc(dl)
@@ -862,17 +875,20 @@ SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
     llvm_unreachable("Unexpected type for ");
 
   case MVT::i8: {
-    MachineSDNode *MUL = DAG.getMachineNode(SH::MULU, DL, VT, Op.getOperand(0), Op.getOperand(1));
+    MachineSDNode *MUL = DAG.getMachineNode(SH::MULU, DL, VT, Op.getOperand(0),
+                                            Op.getOperand(1));
     return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
   }
 
   case MVT::i16: {
-    MachineSDNode *MUL = DAG.getMachineNode(SH::MULS, DL, VT, Op.getOperand(0), Op.getOperand(1));
+    MachineSDNode *MUL = DAG.getMachineNode(SH::MULS, DL, VT, Op.getOperand(0),
+                                            Op.getOperand(1));
     return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
   }
 
   case MVT::i32: {
-    MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0), Op.getOperand(1));
+    MachineSDNode *MUL = DAG.getMachineNode(SH::MULL, DL, VT, Op.getOperand(0),
+                                            Op.getOperand(1));
     return DAG.getCopyFromReg(SDValue(MUL, 0), DL, SH::MACLO, VT);
   }
 
@@ -887,7 +903,8 @@ SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
       Args.push_back(Entry);
     }
 
-    RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(RTLIB::MUL_I32);
+    RTLIB::LibcallImpl LCImpl =
+        DAG.getLibcalls().getLibcallImpl(RTLIB::MUL_I32);
     if (LCImpl == RTLIB::Unsupported)
       return SDValue();
 
@@ -896,12 +913,11 @@ SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
 
     Type *RetTy = (Type *)StructType::get(Ty, Ty);
 
-
     TargetLowering::CallLoweringInfo CLI(DAG);
     CLI.setDebugLoc(DL)
         .setChain(InChain)
-        .setLibCallee(DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy,
-                      Callee, std::move(Args))
+        .setLibCallee(DAG.getLibcalls().getLibcallImplCallingConv(LCImpl),
+                      RetTy, Callee, std::move(Args))
         .setInRegister();
 
     std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
@@ -917,8 +933,9 @@ SDValue SuperHTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
 //                              CUSTOM LOWERING
 //===----------------------------------------------------------------------===//
 
-SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
-  switch(Op->getOpcode()) {
+SDValue SuperHTargetLowering::LowerOperation(SDValue Op,
+                                             SelectionDAG &DAG) const {
+  switch (Op->getOpcode()) {
   case ISD::UDIV:
   case ISD::SDIV:
     return LowerDIV(Op, DAG);
@@ -955,8 +972,9 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) cons
 //                          SelectCC/SetCC Lowering
 //===----------------------------------------------------------------------===//
 
-MachineBasicBlock *SuperHTargetLowering::insertSELECTCC(MachineInstr &MI, 
-                                                        MachineBasicBlock *MBB) const {
+MachineBasicBlock *
+SuperHTargetLowering::insertSELECTCC(MachineInstr &MI,
+                                     MachineBasicBlock *MBB) const {
   DEBUG_FN_PRINT()
 
   MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
@@ -1045,13 +1063,13 @@ MachineBasicBlock *SuperHTargetLowering::insertSELECTCC(MachineInstr &MI,
 //                              CUSTOM LOWERING
 //===----------------------------------------------------------------------===//
 
-MachineBasicBlock *
-SuperHTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
-                                                  MachineBasicBlock *MBB) const {
+MachineBasicBlock *SuperHTargetLowering::EmitInstrWithCustomInserter(
+    MachineInstr &MI, MachineBasicBlock *MBB) const {
   int Op = MI.getOpcode();
 
   switch (Op) {
-  default: break;
+  default:
+    break;
   case SH::Select8:
   case SH::Select16:
   case SH::Select32:
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 5b66a6b9ca725..0b484c9323250 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -16,16 +16,16 @@
 
 #include "SuperH.h"
 #include "SuperHInstrInfo.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/IR/GlobalValue.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
 
 namespace llvm {
 class SuperHSubtarget;
 class MachineConstantPool;
 
-class SuperHTargetLowering : public TargetLowering  {
+class SuperHTargetLowering : public TargetLowering {
   const SuperHSubtarget *Subtarget;
 
 public:
@@ -34,11 +34,11 @@ class SuperHTargetLowering : public TargetLowering  {
   /// ReplaceNodeResults - Replace a node with an illegal result type
   /// with a new node built out of custom code.
   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
-                                           SelectionDAG &DAG) const override;
+                          SelectionDAG &DAG) const override;
 
-  // LowerToConstantPool - SuperH's compressed instruction set means that 
-  // immediates and displacements can not be larger than 8 bits. 
-  // As such we need to store said immediates and displacements within 
+  // LowerToConstantPool - SuperH's compressed instruction set means that
+  // immediates and displacements can not be larger than 8 bits.
+  // As such we need to store said immediates and displacements within
   // constants that are within range of the program counter.
   //
   // As such this function is a helper that:
@@ -46,27 +46,27 @@ class SuperHTargetLowering : public TargetLowering  {
   //  2. Inserts the target address into said slot.
   //  3. Returns the neccesary, but non-legalized instruction sequence to fetch
   //     the address from that constant pool slot.
-  template<class NodeTy>
-  SDValue LowerToConstantPool(NodeTy* N, SelectionDAG &DAG) const;
-
-  SDValue LowerFormalArguments(SDValue Chain,
-                         CallingConv::ID CallConv, bool IsVarArg,
-                         const SmallVectorImpl<ISD::InputArg> &Ins,
-                         const SDLoc &dl, SelectionDAG &DAG,
-                         SmallVectorImpl<SDValue> &InVals) const override;
-  SDValue LowerReturn(SDValue Chain,
-                      CallingConv::ID CallConv, bool IsVarArg,
+  template <class NodeTy>
+  SDValue LowerToConstantPool(NodeTy *N, SelectionDAG &DAG) const;
+
+  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;
+                      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;
 
   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
-  
+
   // Lowerings
   SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
@@ -78,28 +78,29 @@ class SuperHTargetLowering : public TargetLowering  {
   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
-  SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
-                   SDValue &OutCC, SelectionDAG &DAG, SDLoc DL) const;
+  SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &OutCC,
+                   SelectionDAG &DAG, SDLoc DL) const;
 
   // Inserters
   MachineBasicBlock *
   EmitInstrWithCustomInserter(MachineInstr &MI,
                               MachineBasicBlock *MBB) const override;
+
 private:
-  MachineBasicBlock *insertSELECTCC(MachineInstr &MI, 
+  MachineBasicBlock *insertSELECTCC(MachineInstr &MI,
                                     MachineBasicBlock *BB) const;
-  MachineBasicBlock *insertLoad(MachineInstr &MI, 
-                                MachineBasicBlock *BB) const;
-  MachineBasicBlock *insertStore(MachineInstr &MI, 
-                                 MachineBasicBlock *BB) const;
+  MachineBasicBlock *insertLoad(MachineInstr &MI, MachineBasicBlock *BB) const;
+  MachineBasicBlock *insertStore(MachineInstr &MI, MachineBasicBlock *BB) const;
 
-  SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override;
+  SDValue getPICJumpTableRelocBase(SDValue Table,
+                                   SelectionDAG &DAG) const override;
 
   // Lowerings
-  SDValue LowerCallResult(
-    SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
-    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
-    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const;
+  SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
+                          CallingConv::ID CallConv, bool isVarArg,
+                          const SmallVectorImpl<ISD::InputArg> &Ins,
+                          const SDLoc &dl, SelectionDAG &DAG,
+                          SmallVectorImpl<SDValue> &InVals) const;
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index c144341f3b126..4d9ca9efa7bd3 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -12,12 +12,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "SuperHInstrInfo.h"
+#include "MCTargetDesc/SuperHInstPrinter.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
+#include "SuperH.h"
 #include "SuperHRegisterInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
-#include "MCTargetDesc/SuperHInstPrinter.h"
-#include "SuperH.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
@@ -29,9 +29,9 @@
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrInfo.h"
-#include "llvm/Support/ErrorHandling.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
 
 using namespace llvm;
@@ -43,23 +43,20 @@ using namespace llvm;
 
 SuperHInstrInfo::SuperHInstrInfo(const SuperHSubtarget &ST)
     : SuperHGenInstrInfo(ST, RI, SH::ADJCALLSTACKDOWN, SH::ADJCALLSTACKUP),
-      RI(ST), Subtarget(ST) { }
+      RI(ST), Subtarget(ST) {}
 
 // Pin the vtable to this file.
 void SuperHInstrInfo::anchor() {}
 
-
 // Gets whether a given opcode can fill a delay slot.
-// 
-// SuperH does not allow branch instructions of any kind to be situated 
+//
+// SuperH does not allow branch instructions of any kind to be situated
 // in a delay slot, nor does it allow instructions with delay slots
 // to be chained together.
 bool SuperHInstrInfo::canFillDelaySlot(unsigned Opcode) const {
   auto Desc = this->get(Opcode);
-  return !Desc.hasDelaySlot() && 
-         !Desc.isBranch() && 
-         !Desc.isCall() && !Desc.isReturn() &&
-         !(Desc.TSFlags & 0x1);
+  return !Desc.hasDelaySlot() && !Desc.isBranch() && !Desc.isCall() &&
+         !Desc.isReturn() && !(Desc.TSFlags & 0x1);
 }
 
 /// Return the noop instruction to use for a noop.
@@ -69,7 +66,7 @@ MCInst SuperHInstrInfo::getNop() const {
   return I;
 }
 
-void SuperHInstrInfo::insertNoop(MachineBasicBlock &MBB, 
+void SuperHInstrInfo::insertNoop(MachineBasicBlock &MBB,
                                  MachineBasicBlock::iterator MI) const {
   BuildMI(&MBB, MI->getDebugLoc(), get(SH::NOP));
 }
@@ -90,13 +87,17 @@ SHCC::CondCode SuperHInstrInfo::getCondFromBranchOp(unsigned Op) const {
 
 SHCC::CondCode SuperHInstrInfo::getOppositeCondCode(SHCC::CondCode Op) const {
   switch (Op) {
-  default:              return SHCC::COND_INVALID;
-  case SHCC::COND_T:    return SHCC::COND_F;
-  case SHCC::COND_F:    return SHCC::COND_T;
+  default:
+    return SHCC::COND_INVALID;
+  case SHCC::COND_T:
+    return SHCC::COND_F;
+  case SHCC::COND_F:
+    return SHCC::COND_T;
   }
 }
 
-const MCInstrDesc &SuperHInstrInfo::getBrCond(SHCC::CondCode CC, bool delaySlot) const {
+const MCInstrDesc &SuperHInstrInfo::getBrCond(SHCC::CondCode CC,
+                                              bool delaySlot) const {
   switch (CC) {
   default:
     llvm_unreachable("Unknown condition code!");
@@ -138,10 +139,10 @@ unsigned SuperHInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
 //===----------------------------------------------------------------------===//
 
 void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
-                           MachineBasicBlock::iterator MI, const DebugLoc &DL,
-                           Register DestReg, Register SrcReg, bool KillSrc,
-                           bool RenamableDest,
-                           bool RenamableSrc) const {
+                                  MachineBasicBlock::iterator MI,
+                                  const DebugLoc &DL, Register DestReg,
+                                  Register SrcReg, bool KillSrc,
+                                  bool RenamableDest, bool RenamableSrc) const {
   // Do nothing, self copy.
   if (SrcReg == DestReg)
     return;
@@ -149,21 +150,21 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   // Load from MACL
   if (SrcReg == SH::MACLO && SH::GPRRegClass.contains(DestReg)) {
     BuildMI(MBB, MI, DL, get(SH::STSMACL), DestReg)
-      .addReg(SrcReg, getKillRegState(KillSrc));
+        .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   }
 
   // Store to MACL
   if (SH::GPRRegClass.contains(SrcReg) && DestReg == SH::MACLO) {
     BuildMI(MBB, MI, DL, get(SH::LDSMACL), DestReg)
-      .addReg(SrcReg, getKillRegState(KillSrc));
+        .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   }
 
   // If the targets are GPR registers, use MOV Rm, Rn.
   if (SH::GPRRegClass.contains(DestReg, SrcReg)) {
     BuildMI(MBB, MI, DL, get(SH::MOV), DestReg)
-      .addReg(SrcReg, getKillRegState(KillSrc));
+        .addReg(SrcReg, getKillRegState(KillSrc));
     return;
   };
 
@@ -171,15 +172,12 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   llvm_unreachable("Impossible reg-to-reg copy");
 }
 
-
-
-
-
 //===----------------------------------------------------------------------===//
 //                              Stack Frames
 //===----------------------------------------------------------------------===//
 
-Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const {
+Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
+                                             int &FrameIndex) const {
   if (MI.getOperand(0).isReg() && MI.getOperand(1).isFI() &&
       MI.getOperand(2).getImm() == 0) {
     FrameIndex = MI.getOperand(1).getIndex();
@@ -188,21 +186,23 @@ Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameI
   return 0;
 }
 
-void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, 
-                                          Register SrcReg, bool isKill, int FrameIndex, 
-                                          const TargetRegisterClass *RC, Register VReg, 
-                                          MachineInstr::MIFlag Flags) const {
+void SuperHInstrInfo::storeRegToStackSlot(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator II, Register SrcReg,
+    bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
+    MachineInstr::MIFlag Flags) const {
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   uint ObjectSize = MFI.getObjectSize(FrameIndex);
 
-  LLVM_DEBUG(dbgs() << "Store " << (SrcReg > RI.getNumRegs() ? "VREG" : RI.getName(SrcReg)) 
-                    << " to slot " << FrameIndex
-                    << " size=" << ObjectSize << "\n");
+  LLVM_DEBUG(dbgs() << "Store "
+                    << (SrcReg > RI.getNumRegs() ? "VREG" : RI.getName(SrcReg))
+                    << " to slot " << FrameIndex << " size=" << ObjectSize
+                    << "\n");
 
   unsigned Opc;
-  switch(ObjectSize) {
-  default: llvm_unreachable("Cannot store this register into stack slot!");
+  switch (ObjectSize) {
+  default:
+    llvm_unreachable("Cannot store this register into stack slot!");
   case 1:
     Opc = SH::MOVBSPtr;
     break;
@@ -214,13 +214,14 @@ void SuperHInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBl
     break;
   }
   BuildMI(MBB, II, DebugLoc(), get(Opc))
-    .addReg(SrcReg, getKillRegState(isKill))
-    .addFrameIndex(FrameIndex)
-    .addImm(0);
+      .addReg(SrcReg, getKillRegState(isKill))
+      .addFrameIndex(FrameIndex)
+      .addImm(0);
 }
 
-Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const {
-  if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() && 
+Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
+                                              int &FrameIndex) const {
+  if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
       MI.getOperand(1).getImm() == 0) {
     FrameIndex = MI.getOperand(0).getIndex();
     return MI.getOperand(2).getReg();
@@ -228,21 +229,25 @@ Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &Frame
   return 0;
 }
 
-void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, 
-                                           Register DestReg, int FrameIndex, 
-                                           const TargetRegisterClass *RC, Register VReg,
-                                           unsigned SubReg, MachineInstr::MIFlag Flags) const {
+void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
+                                           MachineBasicBlock::iterator II,
+                                           Register DestReg, int FrameIndex,
+                                           const TargetRegisterClass *RC,
+                                           Register VReg, unsigned SubReg,
+                                           MachineInstr::MIFlag Flags) const {
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   uint ObjectSize = MFI.getObjectSize(FrameIndex);
 
-  LLVM_DEBUG(dbgs() << "Load " << (DestReg > RI.getNumRegs() ? "VREG" : RI.getName(DestReg)) 
-                    << " from slot " << FrameIndex
-                    << " size=" << ObjectSize << "\n");
-  
+  LLVM_DEBUG(
+      dbgs() << "Load "
+             << (DestReg > RI.getNumRegs() ? "VREG" : RI.getName(DestReg))
+             << " from slot " << FrameIndex << " size=" << ObjectSize << "\n");
+
   unsigned Opc;
-  switch(ObjectSize) {
-  default: llvm_unreachable("Cannot load this register from stack slot!");
+  switch (ObjectSize) {
+  default:
+    llvm_unreachable("Cannot load this register from stack slot!");
   case 1:
     Opc = SH::MOVBLPtr;
     break;
@@ -255,8 +260,8 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
   }
 
   BuildMI(MBB, II, DebugLoc(), get(Opc), DestReg)
-    .addFrameIndex(FrameIndex)
-    .addImm(0);
+      .addFrameIndex(FrameIndex)
+      .addImm(0);
 }
 
 
@@ -266,10 +271,11 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicB
 //                              Branch Analysis
 //===----------------------------------------------------------------------===//
 
-bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
-                   MachineBasicBlock *&FBB,
-                   SmallVectorImpl<MachineOperand> &Cond,
-                   bool AllowModify) const {
+bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
+                                    MachineBasicBlock *&TBB,
+                                    MachineBasicBlock *&FBB,
+                                    SmallVectorImpl<MachineOperand> &Cond,
+                                    bool AllowModify) const {
   // Start from the bottom of the block and work up, examining the
   // terminator instructions.
   MachineBasicBlock::iterator I = MBB.end();
@@ -380,10 +386,9 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&
   return false;
 }
 
-unsigned SuperHInstrInfo::insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
-                      MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
-                      const DebugLoc &DL,
-                      int *BytesAdded) const {
+unsigned SuperHInstrInfo::insertBranch(
+    MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
+    ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
   if (BytesAdded)
     *BytesAdded = 0;
 
@@ -421,7 +426,7 @@ unsigned SuperHInstrInfo::insertBranch(MachineBasicBlock &MBB, MachineBasicBlock
 }
 
 unsigned SuperHInstrInfo::removeBranch(MachineBasicBlock &MBB,
-                      int *BytesRemoved) const {
+                                       int *BytesRemoved) const {
   if (BytesRemoved)
     *BytesRemoved = 0;
 
@@ -450,8 +455,8 @@ unsigned SuperHInstrInfo::removeBranch(MachineBasicBlock &MBB,
   return Count;
 }
 
-bool
-SuperHInstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
+bool SuperHInstrInfo::reverseBranchCondition(
+    SmallVectorImpl<MachineOperand> &Cond) const {
   assert(Cond.size() == 1 && "Invalid SH branch condition!");
 
   SHCC::CondCode CC = (SHCC::CondCode)Cond[0].getImm();
@@ -459,7 +464,8 @@ SuperHInstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) c
   return false;
 }
 
-MachineBasicBlock *SuperHInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
+MachineBasicBlock *
+SuperHInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
   if (MI.isBranch())
     return MI.getOperand(0).getMBB();
 
@@ -467,7 +473,7 @@ MachineBasicBlock *SuperHInstrInfo::getBranchDestBlock(const MachineInstr &MI) c
 }
 
 bool SuperHInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
-                           int64_t BrOffset) const {
+                                            int64_t BrOffset) const {
   switch (BranchOp) {
   default:
     llvm_unreachable("unexpected opcode!");
@@ -481,4 +487,3 @@ bool SuperHInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
     return isIntN(12, BrOffset);
   }
 }
-
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index a944d2089df1b..b74c2b286cc90 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -15,10 +15,10 @@
 #define LLVM_LIB_TARGET_SUPERH_SUPERHINSTRINFO_H
 
 #include "SuperHRegisterInfo.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
-#include "llvm/CodeGen/ISDOpcodes.h"
 
 #define GET_INSTRINFO_HEADER
 #include "SuperHGenInstrInfo.inc"
@@ -60,8 +60,8 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   const SuperHRegisterInfo &getRegisterInfo() const { return RI; }
 
   /// Gets whether a given opcode can fill a delay slot.
-  /// 
-  /// SuperH does not allow branch instructions of any kind to be situated 
+  ///
+  /// SuperH does not allow branch instructions of any kind to be situated
   /// in a delay slot, nor does it allow instructions with delay slots
   /// to be chained together.
   bool canFillDelaySlot(unsigned Opcode) const;
@@ -74,16 +74,14 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
 
   /// Return the noop instruction to use for a noop.
   MCInst getNop() const override;
-  void insertNoop(MachineBasicBlock &MBB, 
+  void insertNoop(MachineBasicBlock &MBB,
                   MachineBasicBlock::iterator MI) const override;
 
-
   // Stack Frames
-  void copyPhysReg(MachineBasicBlock &MBB,
-                           MachineBasicBlock::iterator MI, const DebugLoc &DL,
-                           Register DestReg, Register SrcReg, bool KillSrc,
-                           bool RenamableDest = false,
-                           bool RenamableSrc = false) const override;
+  void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+                   const DebugLoc &DL, Register DestReg, Register SrcReg,
+                   bool KillSrc, bool RenamableDest = false,
+                   bool RenamableSrc = false) const override;
   void storeRegToStackSlot(
       MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
       bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
@@ -98,7 +96,6 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   Register isStoreToStackSlot(const MachineInstr &MI,
                               int &FrameIndex) const override;
 
-
   // Branch Analysis
   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
                      MachineBasicBlock *&FBB,
@@ -120,6 +117,6 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
 };
 
 const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
-}
+} // namespace llvm
 
 #endif // end LLVM_LIB_TARGET_SUPERH_SUPERHINSTRINFO_H
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
index d64518bac837f..dce566a20f2aa 100644
--- a/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMCInstLower.cpp
@@ -7,14 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "SuperHMCInstLower.h"
-#include "MCTargetDesc/SuperHMCAsmInfo.h"
 #include "MCTargetDesc/SuperHBaseInfo.h"
+#include "MCTargetDesc/SuperHMCAsmInfo.h"
 #include "SuperHSubtarget.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 
-
 namespace llvm {
 
 MCOperand
@@ -51,7 +50,8 @@ SuperHMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
 
 void SuperHMCInstLower::lowerInstruction(const MachineInstr &MI,
                                          MCInst &OutMI) const {
-  auto &Subtarget = MI.getParent()->getParent()->getSubtarget<SuperHSubtarget>();
+  auto &Subtarget =
+      MI.getParent()->getParent()->getSubtarget<SuperHSubtarget>();
 
   OutMI.setOpcode(MI.getOpcode());
   for (MachineOperand const &MO : MI.operands()) {
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
index dd009e48c198f..944f196aa250b 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -29,47 +29,42 @@ MachineFunctionInfo *SuperHMachineFunctionInfo::clone(
 }
 
 SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
-        GlobalAddressSDNode *N, 
-        SelectionDAG &DAG, 
-        SHCP::SHCPModifier Modifier) {
+    GlobalAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier) {
 
   // Early exit for null node.
   if (!N)
     return nullptr;
 
-  // Run though the constant pool that is tied to the DAG and search for 
+  // Run though the constant pool that is tied to the DAG and search for
   // the constant there.
   MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
   for (auto &MC : MCP->getConstants()) {
     if (MC.isMachineConstantPoolEntry()) {
-      if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+      if (auto *CPV = (SuperHConstantPoolConstant *)MC.Val.MachineCPVal) {
         if (CPV->getGV() == N->getGlobal())
           return CPV;
       }
     }
   }
-  
+
   // If not found, create a new one and add it.
   MachineFunction &MF = DAG.getMachineFunction();
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
   unsigned LabelIndex = SFI->createConstIndex();
-  return SuperHConstantPoolConstant::Create(
-    N->getGlobal(), 
-    LabelIndex,
-    SHCP::SHCPKind::CPValue,
-    Modifier
-  );
+  return SuperHConstantPoolConstant::Create(N->getGlobal(), LabelIndex,
+                                            SHCP::SHCPKind::CPValue, Modifier);
 }
 
 SuperHConstantPoolConstant *
-SuperHMachineFunctionInfo::tryGetConstant(const GlobalValue *G, const MachineFunction& MF) const {
+SuperHMachineFunctionInfo::tryGetConstant(const GlobalValue *G,
+                                          const MachineFunction &MF) const {
 
-  // Run though the constant pool that is tied to the DAG and search for 
+  // Run though the constant pool that is tied to the DAG and search for
   // the constant there.
   const MachineConstantPool *MCP = MF.getConstantPool();
   for (auto &MC : MCP->getConstants()) {
     if (MC.isMachineConstantPoolEntry()) {
-      if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+      if (auto *CPV = (SuperHConstantPoolConstant *)MC.Val.MachineCPVal) {
         if (CPV->getGV() == G)
           return CPV;
       }
@@ -79,20 +74,18 @@ SuperHMachineFunctionInfo::tryGetConstant(const GlobalValue *G, const MachineFun
 }
 
 SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
-        BlockAddressSDNode *N, 
-        SelectionDAG &DAG, 
-        SHCP::SHCPModifier Modifier) {
+    BlockAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier) {
 
   // Early exit for null node.
   if (!N)
     return nullptr;
 
-  // Run though the constant pool that is tied to the DAG and search for 
+  // Run though the constant pool that is tied to the DAG and search for
   // the constant there.
   MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
   for (auto &MC : MCP->getConstants()) {
     if (MC.isMachineConstantPoolEntry()) {
-      if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+      if (auto *CPV = (SuperHConstantPoolConstant *)MC.Val.MachineCPVal) {
         if (CPV->getBlockAddress() == N->getBlockAddress())
           return CPV;
       }
@@ -103,29 +96,25 @@ SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
   MachineFunction &MF = DAG.getMachineFunction();
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
   unsigned LabelIndex = SFI->createConstIndex();
-  return SuperHConstantPoolConstant::Create(
-    N->getBlockAddress(), 
-    LabelIndex,
-    SHCP::SHCPKind::CPBlockAddress,
-    Modifier
-  );
+  return SuperHConstantPoolConstant::Create(N->getBlockAddress(), LabelIndex,
+                                            SHCP::SHCPKind::CPBlockAddress,
+                                            Modifier);
 }
 
-SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
-        ConstantSDNode *N, 
-        SelectionDAG &DAG, 
-        SHCP::SHCPModifier Modifier) {
+SuperHConstantPoolConstant *
+SuperHMachineFunctionInfo::tryGetConstant(ConstantSDNode *N, SelectionDAG &DAG,
+                                          SHCP::SHCPModifier Modifier) {
 
   // Early exit for null node.
   if (!N)
     return nullptr;
 
-  // Run though the constant pool that is tied to the DAG and search for 
+  // Run though the constant pool that is tied to the DAG and search for
   // the constant there.
   MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
   for (auto &MC : MCP->getConstants()) {
     if (MC.isMachineConstantPoolEntry()) {
-      if (auto *CPV = (SuperHConstantPoolConstant*)MC.Val.MachineCPVal) {
+      if (auto *CPV = (SuperHConstantPoolConstant *)MC.Val.MachineCPVal) {
         if (CPV->getPromotedGlobalInit() == N->getConstantIntValue())
           return CPV;
       }
@@ -137,41 +126,33 @@ SuperHConstantPoolConstant *SuperHMachineFunctionInfo::tryGetConstant(
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
   unsigned LabelIndex = SFI->createConstIndex();
   return SuperHConstantPoolConstant::Create(
-    N->getConstantIntValue(), 
-    LabelIndex,
-    SHCP::SHCPKind::CPPromotedGlobal,
-    Modifier
-  );
+      N->getConstantIntValue(), LabelIndex, SHCP::SHCPKind::CPPromotedGlobal,
+      Modifier);
 }
 
 SuperHConstantPoolSymbol *SuperHMachineFunctionInfo::tryGetConstant(
-        ExternalSymbolSDNode *N, 
-        SelectionDAG &DAG, 
-        SHCP::SHCPModifier Modifier) {
+    ExternalSymbolSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier) {
 
   // Early exit for null node.
   if (!N)
     return nullptr;
 
-  // Run though the constant pool that is tied to the DAG and search for 
+  // Run though the constant pool that is tied to the DAG and search for
   // the constant there.
   MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
   for (auto &MC : MCP->getConstants()) {
     if (MC.isMachineConstantPoolEntry()) {
-      if (auto *CPV = (SuperHConstantPoolSymbol*)MC.Val.MachineCPVal) {
+      if (auto *CPV = (SuperHConstantPoolSymbol *)MC.Val.MachineCPVal) {
         if (CPV->getSymbol() == N->getSymbol())
           return CPV;
       }
     }
   }
-  
+
   // If not found, create a new one and add it.
   MachineFunction &MF = DAG.getMachineFunction();
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
   unsigned LabelIndex = SFI->createConstIndex();
-  return SuperHConstantPoolSymbol::Create(
-    *DAG.getContext(), 
-    N->getSymbol(),
-    LabelIndex
-  );
+  return SuperHConstantPoolSymbol::Create(*DAG.getContext(), N->getSymbol(),
+                                          LabelIndex);
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
index a162f3dc36244..bc85d83de3d55 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -26,7 +26,7 @@ namespace llvm {
 
 class SuperHMachineFunctionInfo : public MachineFunctionInfo {
 
-  /// CPIndexCount - How many constant pool indices are allocated. 
+  /// CPIndexCount - How many constant pool indices are allocated.
   unsigned CPIndexCount = 0;
 
   BitVector UsedRegs;
@@ -47,9 +47,9 @@ class SuperHMachineFunctionInfo : public MachineFunctionInfo {
   // createConstIndex - Creates a new PIC Label UId.
   unsigned createConstIndex() { return CPIndexCount++; }
 
-  // tryGetConstant - SuperH's compressed instruction set means that 
-  // immediates and displacements can not be larger than 8 bits. 
-  // As such we need to store said immediates and displacements within 
+  // tryGetConstant - SuperH's compressed instruction set means that
+  // immediates and displacements can not be larger than 8 bits.
+  // As such we need to store said immediates and displacements within
   // constants that are within range of the program counter.
   //
   // As such this function is a helper that:
@@ -57,19 +57,27 @@ class SuperHMachineFunctionInfo : public MachineFunctionInfo {
   //  2. Inserts the target into said slot.
   //  3. Returns the allocated slot, ready to be loaded via
   //     a PC-relative load.
-  SuperHConstantPoolConstant *tryGetConstant(GlobalAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
-  SuperHConstantPoolConstant *tryGetConstant(BlockAddressSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
-  SuperHConstantPoolConstant *tryGetConstant(ConstantSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
-  SuperHConstantPoolSymbol *tryGetConstant(ExternalSymbolSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant *tryGetConstant(GlobalAddressSDNode *N,
+                                             SelectionDAG &DAG,
+                                             SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant *tryGetConstant(BlockAddressSDNode *N,
+                                             SelectionDAG &DAG,
+                                             SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant *tryGetConstant(ConstantSDNode *N,
+                                             SelectionDAG &DAG,
+                                             SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolSymbol *tryGetConstant(ExternalSymbolSDNode *N,
+                                           SelectionDAG &DAG,
+                                           SHCP::SHCPModifier Modifier);
 
   // Helper for lower level passes that gets global value constants.
-  SuperHConstantPoolConstant *tryGetConstant(const GlobalValue *G, const MachineFunction& MF) const;
+  SuperHConstantPoolConstant *tryGetConstant(const GlobalValue *G,
+                                             const MachineFunction &MF) const;
 
 private:
-	virtual void anchor();
+  virtual void anchor();
 };
 
-
 } // namespace llvm
 
 #endif
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 119031c530ccf..470e1e6dfda9a 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -13,10 +13,10 @@
 
 #include "SuperHRegisterInfo.h"
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
-#include "SuperHTargetMachine.h"
+#include "SuperH.h"
 #include "SuperHFrameLowering.h"
 #include "SuperHSubtarget.h"
-#include "SuperH.h"
+#include "SuperHTargetMachine.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/Register.h"
@@ -37,28 +37,33 @@ using namespace llvm;
 
 
 SuperHRegisterInfo::SuperHRegisterInfo(const SuperHSubtarget &ST)
-  : SuperHGenRegisterInfo(SH::R0, /*DwarfFlavour*/0, /*EHFlavor*/0,
-                         /*PC*/SH::PC), Subtarget(ST) {}
+    : SuperHGenRegisterInfo(SH::R0, /*DwarfFlavour*/ 0, /*EHFlavor*/ 0,
+                            /*PC*/ SH::PC),
+      Subtarget(ST) {}
 
-const TargetRegisterClass *SuperHRegisterInfo::getPointerRegClass(unsigned Kind) const {
+const TargetRegisterClass *
+SuperHRegisterInfo::getPointerRegClass(unsigned Kind) const {
   return &SH::GPRRegClass;
 }
 
-const MCPhysReg *SuperHRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
+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; 
+const uint32_t *
+SuperHRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
+                                         CallingConv::ID CC) const {
+  return CSR_SH_RegMask;
 }
 
 const uint32_t *SuperHRegisterInfo::getNoPreservedMask() const {
-  return CSR_SH_RegMask; 
+  return CSR_SH_RegMask;
 }
 
 const TargetRegisterClass *
 SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
-                                           const MachineFunction &MF) const {
+                                              const MachineFunction &MF) const {
   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
 
   if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
@@ -82,10 +87,10 @@ BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
 
   // R0 is always reserved as some instructions can only write to it.
   Reserved.set(SH::R0);
-  
+
   // R1 is generally used as the temporary storage for addresses.
   Reserved.set(SH::R1);
-  
+
   // Also reserve the stack pointer.
   Reserved.set(SH::R15);
 
@@ -109,29 +114,31 @@ static void replaceFI(const MachineFunction &MF, MachineBasicBlock::iterator II,
 }
 
 bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
-                                           int SPAdj,
-                                           unsigned FIOperandNum,
-                                           RegScavenger *RS) const {
+                                             int SPAdj, unsigned FIOperandNum,
+                                             RegScavenger *RS) const {
   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 TargetFrameLowering *TFI = TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
-  const TargetInstrInfo &TII = *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
+  const TargetFrameLowering *TFI =
+      TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
+  const TargetInstrInfo &TII =
+      *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
 
   // Get the register offset to fetch.
   Register FrameReg;
-  int64_t Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
+  int64_t Offset =
+      TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
 
   LLVM_DEBUG({
-    int64_t Fo = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
-    dbgs()  << "Eliminiate FI " << FrameIndex << " @ SP["
-            << -Fo << "]...\n";
+    int64_t Fo =
+        TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
+    dbgs() << "Eliminiate FI " << FrameIndex << " @ SP[" << -Fo << "]...\n";
   });
-  
+
   replaceFI(MF, II, MI, DL, FIOperandNum, Offset, FrameReg);
   return false;
 }
@@ -141,14 +148,8 @@ Register SuperHRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
   return TFI->hasFP(MF) ? SH::R14 : SH::R15;
 }
 
-Register SuperHRegisterInfo::getFrameRegister() const {
-  return SH::R14;
-}
+Register SuperHRegisterInfo::getFrameRegister() const { return SH::R14; }
 
-Register SuperHRegisterInfo::getStackRegister() const {
-  return SH::R15;
-}
+Register SuperHRegisterInfo::getStackRegister() const { return SH::R15; }
 
-Register SuperHRegisterInfo::getGOTRegister() const {
-  return SH::R12;
-}
\ No newline at end of file
+Register SuperHRegisterInfo::getGOTRegister() const { return SH::R12; }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index 921d966aee4b0..50e43d82f9729 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -30,20 +30,24 @@ 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 uint32_t *getCallPreservedMask(const MachineFunction &MF,
+                                       CallingConv::ID CC) const override;
   const uint32_t *getNoPreservedMask() const override;
-  const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const override;
+  const TargetRegisterClass *
+  getPointerRegClass(unsigned Kind = 0) const override;
   BitVector getReservedRegs(const MachineFunction &MF) const override;
-  const TargetRegisterClass *getLargestLegalSuperClass(const TargetRegisterClass *RC,
-                                           const MachineFunction &MF) const override;
+  const TargetRegisterClass *
+  getLargestLegalSuperClass(const TargetRegisterClass *RC,
+                            const MachineFunction &MF) const override;
   Register getFrameRegister(const MachineFunction &MF) const override;
 
   bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
                            unsigned FIOperandNum,
                            RegScavenger *RS = nullptr) const override;
 
-  bool requiresRegisterScavenging(const MachineFunction &MF) const override { return true; }
-
+  bool requiresRegisterScavenging(const MachineFunction &MF) const override {
+    return true;
+  }
 
   // Helpers
   Register getFrameRegister() const;
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
index 93c86db7c50c5..20fae60254d58 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
@@ -28,15 +28,13 @@ using namespace llvm;
 SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &FS,
                                  const TargetMachine &TM)
     : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, CPU, FS), TM(TM),
-      InstrInfo(initializeSubtargetDependencies(CPU, FS)), 
-      TLInfo(TM, *this), TSInfo(), FrameLowering(*this) {
-}
+      InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
+      TSInfo(), FrameLowering(*this) {}
 
 SuperHSubtarget::~SuperHSubtarget() = default;
 
-
-SuperHSubtarget &SuperHSubtarget::initializeSubtargetDependencies(
-    StringRef CPU, StringRef FS) {
+SuperHSubtarget &
+SuperHSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) {
   // Determine default and user specified characteristics
   const Triple &TT = getTargetTriple();
   std::string CPUName = std::string(CPU);
@@ -63,32 +61,25 @@ SHRefClass SuperHSubtarget::classifyBlockAddressReference() const {
   }
   case CodeModel::Medium:
   case CodeModel::Large: {
-    return isPositionIndependent() ? 
-           SHII::MO_PCREL : 
-           SHII::MO_DIR;
+    return isPositionIndependent() ? SHII::MO_PCREL : SHII::MO_DIR;
   }
   }
 }
 
-SHRefClass SuperHSubtarget::classifyLocalReference(const GlobalValue *GV) const {
+SHRefClass
+SuperHSubtarget::classifyLocalReference(const GlobalValue *GV) const {
   switch (TM.getCodeModel()) {
   default:
     llvm_unreachable("Unsupported code model");
   case CodeModel::Small:
   case CodeModel::Kernel: {
-    return isPositionIndependent() ? 
-           SHII::MO_PCREL :
-           SHII::MO_DIR;
+    return isPositionIndependent() ? SHII::MO_PCREL : SHII::MO_DIR;
   }
   case CodeModel::Medium: {
-    return isPositionIndependent() ? 
-           SHII::MO_GOTOFF : 
-           SHII::MO_DIR;
+    return isPositionIndependent() ? SHII::MO_GOTOFF : SHII::MO_DIR;
   }
   case CodeModel::Large: {
-    return isPositionIndependent() ? 
-           SHII::MO_GOTOFF : 
-           SHII::MO_DIR;
+    return isPositionIndependent() ? SHII::MO_GOTOFF : SHII::MO_DIR;
   }
   }
 }
@@ -97,17 +88,16 @@ SHRefClass SuperHSubtarget::classifyExternalReference(const Module &M) const {
   if (TM.shouldAssumeDSOLocal(nullptr))
     return classifyLocalReference(nullptr);
 
-  return isPositionIndependent() ? 
-         SHII::MO_GOTPC : 
-         SHII::MO_GOT;
+  return isPositionIndependent() ? SHII::MO_GOTPC : SHII::MO_GOT;
 }
 
-SHRefClass SuperHSubtarget::classifyGlobalReference(const GlobalValue *GV) const {
+SHRefClass
+SuperHSubtarget::classifyGlobalReference(const GlobalValue *GV) const {
   return classifyGlobalReference(GV, *GV->getParent());
 }
 
 SHRefClass SuperHSubtarget::classifyGlobalReference(const GlobalValue *GV,
-                                   const Module &M) const {
+                                                    const Module &M) const {
   if (TM.shouldAssumeDSOLocal(GV))
     return classifyLocalReference(GV);
 
@@ -117,24 +107,20 @@ SHRefClass SuperHSubtarget::classifyGlobalReference(const GlobalValue *GV,
   case CodeModel::Small:
   case CodeModel::Kernel:
   case CodeModel::Medium: {
-    return isPositionIndependent() ? 
-           SHII::MO_GOTPC : 
-           SHII::MO_DIR;
+    return isPositionIndependent() ? SHII::MO_GOTPC : SHII::MO_DIR;
   }
   case CodeModel::Large: {
-    return isPositionIndependent() ? 
-           SHII::MO_GOTOFF : 
-           SHII::MO_DIR;
+    return isPositionIndependent() ? SHII::MO_GOTOFF : SHII::MO_DIR;
   }
   }
 }
 
-SHRefClass SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
-                                           const Module &M) const {
+SHRefClass
+SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
+                                                 const Module &M) const {
   if (TM.shouldAssumeDSOLocal(GV))
     return SHII::MO_NO_FLAG;
 
-
   // If the function is marked as non-lazy, generate an indirect call
   // which loads from the GOT directly. This avoids run-time overhead
   // at the cost of eager binding.
@@ -143,11 +129,10 @@ SHRefClass SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *G
     return SHII::MO_GOTPC;
   }
 
-  return isPositionIndependent() ? 
-         SHII::MO_PLT : 
-         SHII::MO_DIR;
+  return isPositionIndependent() ? SHII::MO_PLT : SHII::MO_DIR;
 }
 
-SHRefClass SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
+SHRefClass
+SuperHSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const {
   return classifyGlobalFunctionReference(GV, *GV->getParent());
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.h b/llvm/lib/Target/SuperH/SuperHSubtarget.h
index 55c4a0a1ee9ff..31f12524a99e6 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.h
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.h
@@ -55,17 +55,25 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
 #include "SuperHGenSubtargetInfo.inc"
 
 public:
-  SuperHSubtarget(const StringRef &CPU, const StringRef &FS, 
+  SuperHSubtarget(const StringRef &CPU, const StringRef &FS,
                   const TargetMachine &TM);
 
   ~SuperHSubtarget() override;
 
   const Triple &getTargetTriple() const { return TM.getTargetTriple(); }
   const SuperHInstrInfo *getInstrInfo() const override { return &InstrInfo; }
-  const TargetFrameLowering *getFrameLowering() const override { return &FrameLowering; }
-  const SuperHRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); }
-  const SuperHSelectionDAGInfo *getSelectionDAGInfo() const override { return &TSInfo; }
-  const SuperHTargetLowering *getTargetLowering() const override { return &TLInfo; }
+  const TargetFrameLowering *getFrameLowering() const override {
+    return &FrameLowering;
+  }
+  const SuperHRegisterInfo *getRegisterInfo() const override {
+    return &InstrInfo.getRegisterInfo();
+  }
+  const SuperHSelectionDAGInfo *getSelectionDAGInfo() const override {
+    return &TSInfo;
+  }
+  const SuperHTargetLowering *getTargetLowering() const override {
+    return &TLInfo;
+  }
 
   bool isLittleEndian() const { return getTargetTriple().isLittleEndian(); }
   bool isTargetELF() const { return getTargetTriple().isOSBinFormatELF(); }
@@ -87,7 +95,8 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
   /// Classify a global function reference for the current subtarget.
   SHRefClass classifyGlobalFunctionReference(const GlobalValue *GV,
                                              const Module &M) const;
-  SHRefClass classifyGlobalFunctionReference(const GlobalValue *GV) const override;
+  SHRefClass
+  classifyGlobalFunctionReference(const GlobalValue *GV) const override;
 
   /// Classify a blockaddress reference for the current subtarget according to
   /// how we should reference it in a non-pcrel context.
@@ -100,8 +109,7 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
   /// 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 FS);
+  SuperHSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index ecfb8616580ec..ef89a5ea017a2 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -12,8 +12,8 @@
 
 #include "SuperHTargetMachine.h"
 #include "SuperH.h"
-#include "SuperHSubtarget.h"
 #include "SuperHMachineFunctionInfo.h"
+#include "SuperHSubtarget.h"
 #include "TargetInfo/SuperHTargetInfo.h"
 #include "llvm/CodeGen/BranchFoldingPass.h"
 #include "llvm/CodeGen/Passes.h"
@@ -46,7 +46,7 @@ namespace {
 class SuperHPassConfig : public TargetPassConfig {
 public:
   SuperHPassConfig(SuperHTargetMachine &TM, PassManagerBase &PM)
-    : TargetPassConfig(TM, PM) {}
+      : TargetPassConfig(TM, PM) {}
 
   bool addInstSelector() override;
   void addPostRegAlloc() override;
@@ -93,8 +93,8 @@ SuperHTargetMachine::SuperHTargetMachine(const Target &T, const Triple &TT,
                                          CodeGenOptLevel OL, bool JIT)
     : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,
                                RM.value_or(Reloc::Static),
-                               getEffectiveCodeModel(CM, CodeModel::Small),
-                               OL), TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
+                               getEffectiveCodeModel(CM, CodeModel::Small), OL),
+      TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
   initAsmInfo();
 }
 
@@ -117,9 +117,9 @@ SuperHTargetMachine::getSubtargetImpl(const Function &F) const {
   return ST.get();
 }
 
-MachineFunctionInfo *
-SuperHTargetMachine::createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
-                          const TargetSubtargetInfo *STI) const {
-  return SuperHMachineFunctionInfo::create<SuperHMachineFunctionInfo>(Allocator, F,
-                                                                  STI);
+MachineFunctionInfo *SuperHTargetMachine::createMachineFunctionInfo(
+    BumpPtrAllocator &Allocator, const Function &F,
+    const TargetSubtargetInfo *STI) const {
+  return SuperHMachineFunctionInfo::create<SuperHMachineFunctionInfo>(Allocator,
+                                                                      F, STI);
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.h b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
index 63b722fff7a57..5fab6d45aa076 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.h
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
@@ -27,10 +27,10 @@ class SuperHTargetMachine : public CodeGenTargetMachineImpl {
 
 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);
+                      StringRef FS, const TargetOptions &Options,
+                      std::optional<Reloc::Model> RM,
+                      std::optional<CodeModel::Model> CM, CodeGenOptLevel OL,
+                      bool JIT);
   ~SuperHTargetMachine() override;
 
   MachineFunctionInfo *
@@ -42,7 +42,6 @@ class SuperHTargetMachine : public CodeGenTargetMachineImpl {
   TargetLoweringObjectFile *getObjFileLowering() const override {
     return TLOF.get();
   }
-
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
index f206de2dabc90..cc2199bf5c691 100644
--- a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
@@ -22,10 +22,10 @@ Target &llvm::getTheSuperHLETarget() {
   return TheSuperHLETarget;
 }
 
-extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY
-void LLVMInitializeSuperHTargetInfo() {
-  RegisterTarget<Triple::sh, /*HasJIT=*/false> X(getTheSuperHTarget(),
-                                                    "sh", "SuperH (big endian)", "SuperH");
-  RegisterTarget<Triple::shl, /*HasJIT=*/false> Y(getTheSuperHLETarget(),
-                                                    "shl", "SuperH (little endian)", "SuperH");
+extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
+LLVMInitializeSuperHTargetInfo() {
+  RegisterTarget<Triple::sh, /*HasJIT=*/false> X(
+      getTheSuperHTarget(), "sh", "SuperH (big endian)", "SuperH");
+  RegisterTarget<Triple::shl, /*HasJIT=*/false> Y(
+      getTheSuperHLETarget(), "shl", "SuperH (little endian)", "SuperH");
 }

>From 737f353f1f277172024e131f0d65aee8ac34d91e Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 20 Sep 2026 01:17:46 +0200
Subject: [PATCH 52/67] Make targets endian-specific

sh2e and sh3e must use the long form (sh3eeb/sh2eel, etc.)
---
 clang/lib/Basic/Targets.cpp                   |   4 +-
 clang/lib/Basic/Targets/SuperH.cpp            |   2 +-
 clang/lib/CodeGen/CodeGenModule.cpp           |   4 +-
 .../llvm/TargetParser/SuperHTargetParser.h    |  35 +++++
 llvm/include/llvm/TargetParser/Triple.h       |  15 ++-
 llvm/lib/Target/SuperH/SuperH.td              |  70 ++++++++--
 .../SuperH/TargetInfo/SuperHTargetInfo.cpp    |   8 +-
 llvm/lib/TargetParser/CMakeLists.txt          |   1 +
 llvm/lib/TargetParser/SuperHTargetParser.cpp  |  86 ++++++++++++
 llvm/lib/TargetParser/TargetDataLayout.cpp    |   4 +-
 llvm/lib/TargetParser/Triple.cpp              | 122 +++++++++++++++---
 11 files changed, 303 insertions(+), 48 deletions(-)
 create mode 100644 llvm/include/llvm/TargetParser/SuperHTargetParser.h
 create mode 100644 llvm/lib/TargetParser/SuperHTargetParser.cpp

diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index a48e9fe0671c6..3a8e13b96b4ea 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -553,8 +553,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
       return std::make_unique<SparcV9TargetInfo>(Triple, Opts);
     }
     
-  case llvm::Triple::sh:
-  case llvm::Triple::shl:
+  case llvm::Triple::sheb:
+  case llvm::Triple::shel:
     switch (os) {
     default:
       return std::make_unique<SuperHTargetInfo>(Triple, Opts);
diff --git a/clang/lib/Basic/Targets/SuperH.cpp b/clang/lib/Basic/Targets/SuperH.cpp
index e259faa3b3a2a..5c4e97e0dac67 100644
--- a/clang/lib/Basic/Targets/SuperH.cpp
+++ b/clang/lib/Basic/Targets/SuperH.cpp
@@ -22,7 +22,7 @@ struct LLVM_LIBRARY_VISIBILITY SHCPUInfo {
 };
 
 static constexpr SHCPUInfo CPUInfo[] = {
-    {{"sh1"}}, {{"sh2"}}, {{"sh2a"}}, {{"sh3"}}, {{"sh4"}}, {{"sh4a"}},
+    {{"sh1"}}, {{"sh2"}}, {{"sh2e"}}, {{"sh2a"}}, {{"sh3"}}, {{"sh3e"}}, {{"sh4"}}, {{"sh4a"}},
 };
 
 bool SuperHTargetInfo::isValidCPUName(StringRef Name) const {
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 5e4577eb0f5fb..1594f8bb89c36 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -247,8 +247,8 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
     return createRISCVTargetCodeGenInfo(CGM, XLen, ABIFLen, EABI);
   }
 
-  case llvm::Triple::sh:
-  case llvm::Triple::shl: {
+  case llvm::Triple::sheb:
+  case llvm::Triple::shel: {
     return createSuperHTargetCodeGenInfo(CGM);
   }
 
diff --git a/llvm/include/llvm/TargetParser/SuperHTargetParser.h b/llvm/include/llvm/TargetParser/SuperHTargetParser.h
new file mode 100644
index 0000000000000..e8e7bde9b935c
--- /dev/null
+++ b/llvm/include/llvm/TargetParser/SuperHTargetParser.h
@@ -0,0 +1,35 @@
+//===-- SuperHTargetParser - Parser for SuperH target features --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise SuperH hardware features
+// such as FPU/CPU/ARCH/extensions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGETPARSER_SUPERHTARGETPARSER_H
+#define LLVM_TARGETPARSER_SUPERHTARGETPARSER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/TargetParser/Triple.h"
+
+namespace llvm {
+namespace SuperH {
+
+enum class ISAKind { INVALID = 0, SH1, SH2, SH2E, SH2A, SH3, SH3E, SH4, SH4A };
+
+enum class EndianKind { INVALID = 0, LITTLE, BIG };
+
+// SH1-4A
+ISAKind parseArchISA(StringRef ArchName);
+
+// Little/Big endian
+EndianKind parseArchEndian(StringRef ArchName);
+
+} // namespace SuperH
+} // namespace llvm
+#endif
\ No newline at end of file
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index edf2532068c72..223002e2415f3 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -80,8 +80,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 (big endian): sh
-    shl,         // SuperH (little endian): shl
+    sheb,        // SuperH (big endian): sh(e)b
+    shel,        // SuperH (little endian): sh(e)l
     sparc,       // Sparc: sparc
     sparcv9,     // Sparcv9: Sparcv9
     sparcel,     // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
@@ -173,6 +173,15 @@ class Triple {
 
     PPCSubArch_spe,
 
+    SuperHSubArch_1,
+    SuperHSubArch_2,
+    SuperHSubArch_2a,
+    SuperHSubArch_2e,
+    SuperHSubArch_3,
+    SuperHSubArch_3e,
+    SuperHSubArch_4,
+    SuperHSubArch_4a,
+
     // SPIR-V sub-arch corresponds to its version.
     SPIRVSubArch_v10,
     SPIRVSubArch_v11,
@@ -1194,7 +1203,7 @@ class Triple {
 
   /// Tests whether the target is SuperH.
   bool isSuperH() const {
-    return getArch() == Triple::sh || getArch() == Triple::shl;
+    return getArch() == Triple::sheb || getArch() == Triple::shel;
   }
 
   /// Tests whether the target is SystemZ.
diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index eb404c67e61b5..91da9eda8d02a 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -21,21 +21,27 @@ include "llvm/TableGen/SearchableTable.td"
 // SuperH Subtarget features
 //===----------------------------------------------------------------------===//
 
-// NOTE:  Some SH4 CPUs support FSCA and FSRRA despite their
-//        ISA manuals not specifying so.
 def FeatureFPU      : SubtargetFeature<"fp32", "HasFPU", "true",
                                        "Enable use of 32-bit floating point instructions.">;
 def FeatureFPU64    : SubtargetFeature<"fp64", "HasFP64", "true",
                                        "Enable use of 64-bit floating point instructions.",
                                        [FeatureFPU]>;
+
+def FeatureDSP      : SubtargetFeature<"dsp", "HasDSP", "true",
+                                       "Enable SuperH DSP Extensions">;
+
+def FeatureGPRBanks : SubtargetFeature<"gprbanks", "HasGPRBanks", "true",
+                                       "Enable Banked General Purpose Registers">;
+
+// NOTE:  SH-4A implicitly has FSCA and FSRRA, however some earlier processors
+//        of the SH4 variant have a subset of SH-4A's features. As such those
+//        undocumented features are exposed as individual flags.
 def FeatureFSCA     : SubtargetFeature<"fsca", "HasFSCA", "true",
                                        "Enable use of fsca instruction.",
                                        [FeatureFPU]>;
 def FeatureFSRRA    : SubtargetFeature<"fsrra", "HasFSRRA", "true",
                                        "Enable use of fsrra instruction.",
                                        [FeatureFPU]>;
-def FeatureDSP      : SubtargetFeature<"dsp", "HasDSP", "true",
-                                       "Enable SuperH DSP Extensions">;
 
 //===----------------------------------------------------------------------===//
 // SuperH CPU Family features
@@ -49,21 +55,20 @@ def FeatureSH2E     : SubtargetFeature<"sh2e", "SHArchVersion", "SH2E",
                           [FeatureSH2, FeatureFPU]>;
 def FeatureSH2A     : SubtargetFeature<"sh2a", "SHArchVersion", "SH2A",
                           "SH-2A ISA Support",
-                          [FeatureSH2, FeatureFPU, FeatureFPU64]>;
+                          [FeatureSH2]>;
 def FeatureSH3      : SubtargetFeature<"sh3", "SHArchVersion", "SH3",
                           "SH-3 ISA Support",
                           [FeatureSH2]>;
 def FeatureSH3E     : SubtargetFeature<"sh3e", "SHArchVersion", "SH3E",
                           "SH-3E ISA Support",
-                          [FeatureSH2, FeatureFPU]>;
+                          [FeatureSH3, FeatureFPU]>;
 def FeatureSH4      : SubtargetFeature<"sh4", "SHArchVersion", "SH4",
                           "SH-4 ISA Support",
-                          [FeatureSH2, FeatureSH3, FeatureFPU, 
-                           FeatureFPU64]>;
+                          [FeatureSH3, FeatureFPU, FeatureFPU64,
+                           FeatureGPRBanks]>;
 def FeatureSH4A     : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
                           "SH-4A ISA Support",
-                          [FeatureSH2, FeatureSH3, FeatureSH4, 
-                           FeatureFPU, FeatureFPU64, FeatureFSCA, FeatureFSRRA]>;
+                          [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
 
 //===----------------------------------------------------------------------===//
 // SuperH Processors
@@ -71,6 +76,9 @@ def FeatureSH4A     : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
 
 include "SuperHSchedule.td"
 
+class Proc<string n, list<SubtargetFeature> f, list<SubtargetFeature> tunef = []>
+  : Processor<n, NoItineraries, f, tunef>;
+
 class ProcModel<string Name, list<SubtargetFeature> Features>
     : ProcessorModel<Name, GenericSuperHModel, Features>;
 
@@ -86,9 +94,45 @@ def : ProcModel<"sh4a", [FeatureSH4A]>;
 
 // NOTE:  SEGA got some special variants of the SuperH family
 //        produced with some extra features enabled, defining them here.
-def : ProcModel<"dreamcast", [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
-def : ProcModel<"naomi",     [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
-def : ProcModel<"saturn",    [FeatureSH2]>;
+def : Proc<"sh7091",  [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
+def : Proc<"sh7095",  [FeatureSH2]>;
+
+// All of the publicly available CPU cores.
+def : Proc<"sh7020",  []>;
+def : Proc<"sh7021",  []>;
+def : Proc<"sh7131",  [FeatureSH2]>;
+def : Proc<"sh7132",  [FeatureSH2]>;
+def : Proc<"sh7136",  [FeatureSH2]>;
+def : Proc<"sh7137",  [FeatureSH2]>;
+def : Proc<"sh7146",  [FeatureSH2]>;
+def : Proc<"sh7149",  [FeatureSH2]>;
+def : Proc<"sh7124",  [FeatureSH2, FeatureDSP]>;
+def : Proc<"sh7125",  [FeatureSH2, FeatureDSP]>;
+def : Proc<"sh7201",  [FeatureSH2A, FeatureFPU]>;
+def : Proc<"sh7203",  [FeatureSH2A, FeatureFPU, FeatureFPU64]>;
+def : Proc<"sh7205",  [FeatureSH2A]>;
+def : Proc<"sh7206",  [FeatureSH2]>;
+def : Proc<"sh7211",  [FeatureSH2A]>;
+def : Proc<"sh7214",  [FeatureSH2A]>;
+def : Proc<"sh7216",  [FeatureSH2A, FeatureFPU]>;
+def : Proc<"sh7231",  [FeatureSH2A, FeatureFPU]>;
+def : Proc<"sh7237",  [FeatureSH2A]>;
+def : Proc<"sh7239",  [FeatureSH2A, FeatureFPU]>;
+def : Proc<"sh7243",  [FeatureSH2A, FeatureGPRBanks]>;
+def : Proc<"sh7720",  [FeatureSH3, FeatureDSP]>;
+def : Proc<"sh7721",  [FeatureSH3, FeatureDSP]>;
+def : Proc<"sh7750",  [FeatureSH4]>;
+def : Proc<"sh7751",  [FeatureSH4]>;
+def : Proc<"sh7780",  [FeatureSH4A]>;
+def : Proc<"sh7785",  [FeatureSH4A]>;
+def : Proc<"sh7731",  [FeatureSH4A, FeatureDSP]>;
+def : Proc<"sh7734",  [FeatureSH4A]>;
+def : Proc<"sh7722",  [FeatureSH4A, FeatureDSP]>;
+def : Proc<"sh7723",  [FeatureSH4A]>;
+def : Proc<"sh7724",  [FeatureSH4A]>;
+
+// TODO:  Add more families from this listing
+//        https://www.renesas.com/en/document/gde/superh-risc-engine-family-product-part-number-guide?r=1055111
 
 //===----------------------------------------------------------------------===//
 // Register File Description
diff --git a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
index cc2199bf5c691..3b8d1d6e98564 100644
--- a/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
+++ b/llvm/lib/Target/SuperH/TargetInfo/SuperHTargetInfo.cpp
@@ -24,8 +24,8 @@ Target &llvm::getTheSuperHLETarget() {
 
 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
 LLVMInitializeSuperHTargetInfo() {
-  RegisterTarget<Triple::sh, /*HasJIT=*/false> X(
-      getTheSuperHTarget(), "sh", "SuperH (big endian)", "SuperH");
-  RegisterTarget<Triple::shl, /*HasJIT=*/false> Y(
-      getTheSuperHLETarget(), "shl", "SuperH (little endian)", "SuperH");
+  RegisterTarget<Triple::sheb, /*HasJIT=*/false> X(
+      getTheSuperHTarget(), "sheb", "SuperH (big endian)", "SuperH");
+  RegisterTarget<Triple::shel, /*HasJIT=*/false> Y(
+      getTheSuperHLETarget(), "shel", "SuperH (little endian)", "SuperH");
 }
diff --git a/llvm/lib/TargetParser/CMakeLists.txt b/llvm/lib/TargetParser/CMakeLists.txt
index cb45571583d23..fec44fdf3c8d7 100644
--- a/llvm/lib/TargetParser/CMakeLists.txt
+++ b/llvm/lib/TargetParser/CMakeLists.txt
@@ -26,6 +26,7 @@ add_llvm_component_library(LLVMTargetParser
   PPCTargetParser.cpp
   RISCVISAInfo.cpp
   RISCVTargetParser.cpp
+  SuperHTargetParser.cpp
   SubtargetFeature.cpp
   TargetParser.cpp
   Triple.cpp
diff --git a/llvm/lib/TargetParser/SuperHTargetParser.cpp b/llvm/lib/TargetParser/SuperHTargetParser.cpp
new file mode 100644
index 0000000000000..07560907f9ac5
--- /dev/null
+++ b/llvm/lib/TargetParser/SuperHTargetParser.cpp
@@ -0,0 +1,86 @@
+//===-- SuperHTargetParser - Parser for SuperH target features --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise SuperH hardware features
+// such as FPU/CPU/ARCH/extensions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TargetParser/SuperHTargetParser.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+namespace {
+struct SHISA {
+  StringRef Name;
+  SuperH::ISAKind Kind;
+};
+} // namespace
+
+static SuperH::ISAKind consumeISAKind(StringRef &ArchName) {
+  // NOTE:  This list is ordered so that elements that would overrule
+  //        sub-architectures are last, to avoid that exact scenario.
+  static const SHISA ISANames[] = {
+    {"sh2a", SuperH::ISAKind::SH2A},
+    {"sh2e", SuperH::ISAKind::SH2E},
+    {"sh3e", SuperH::ISAKind::SH3E},
+    {"sh4a", SuperH::ISAKind::SH4A},
+    {"sh1", SuperH::ISAKind::SH1},
+    {"sh2", SuperH::ISAKind::SH2},
+    {"sh3", SuperH::ISAKind::SH3},
+    {"sh4", SuperH::ISAKind::SH4},
+
+    // If no subtype is defined, assume 4a, this conforms to
+    // what GCC does.
+    {"sh", SuperH::ISAKind::SH4A},
+  };
+
+  // Check for sh[cpu]
+  for (auto &KV : ISANames) {
+    
+    // Enforce eb suffix for sh2e and sh3e.
+    if (KV.Name.ends_with("e")) {
+      if (!ArchName.ends_with("eb") && !ArchName.ends_with("el"))
+        continue;
+    }
+
+    if (ArchName.consume_front(KV.Name))
+      return KV.Kind;
+  }
+  return SuperH::ISAKind::INVALID;
+}
+
+// SH1-4A
+SuperH::ISAKind SuperH::parseArchISA(StringRef ArchName) {
+  static const StringRef EndianStrings[] = {
+    "l", "el",
+    "b", "eb"
+  };
+
+  // Check for [e]l/b
+  SuperH::ISAKind Kind = consumeISAKind(ArchName);
+  for (auto &P : EndianStrings) {
+    if (ArchName == P)
+      return Kind;
+  }
+
+  return SuperH::ISAKind::INVALID;
+}
+
+// Little/Big endian
+SuperH::EndianKind SuperH::parseArchEndian(StringRef ArchName) {
+  return StringSwitch<SuperH::EndianKind>(ArchName)
+    .EndsWith("eb", EndianKind::BIG)
+    .EndsWith("b", EndianKind::BIG)
+    .EndsWith("el", EndianKind::LITTLE)
+    .EndsWith("l", EndianKind::LITTLE)
+    .Default(EndianKind::INVALID);
+}
\ No newline at end of file
diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp
index 901ea8b892f91..1c8df53eeda8c 100644
--- a/llvm/lib/TargetParser/TargetDataLayout.cpp
+++ b/llvm/lib/TargetParser/TargetDataLayout.cpp
@@ -655,8 +655,8 @@ std::string Triple::computeDataLayout(StringRef ABIName) const {
     return computeSparcDataLayout(*this);
   case Triple::systemz:
     return computeSystemZDataLayout(*this);
-  case Triple::sh:
-  case Triple::shl:
+  case Triple::sheb:
+  case Triple::shel:
     return computeSuperHDataLayout(*this);
   case Triple::tce:
     return "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:32-"
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 89f28ac866110..3b6da9be9a46c 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -18,6 +18,7 @@
 #include "llvm/TargetParser/ARMTargetParser.h"
 #include "llvm/TargetParser/ARMTargetParserCommon.h"
 #include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/SuperHTargetParser.h"
 #include <cassert>
 #include <cstring>
 using namespace llvm;
@@ -119,10 +120,10 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
     return "riscv32be";
   case riscv64be:
     return "riscv64be";
-  case sh:
-    return "sh";
-  case shl:
-    return "shl";
+  case sheb:
+    return "sheb";
+  case shel:
+    return "shel";
   case shave:
     return "shave";
   case sparc:
@@ -204,6 +205,42 @@ StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) {
     if (SubArch == X86_64SubArch_lfi)
       return "x86_64_lfi";
     break;
+  case Triple::sheb:
+    if (SubArch == SuperHSubArch_1)
+      return "sh1eb";
+    if (SubArch == SuperHSubArch_2)
+      return "sh2eb";
+    if (SubArch == SuperHSubArch_2a)
+      return "sh2aeb";
+    if (SubArch == SuperHSubArch_2e)
+      return "sh2eeb";
+    if (SubArch == SuperHSubArch_3)
+      return "sh3eb";
+    if (SubArch == SuperHSubArch_3e)
+      return "sh3eeb";
+    if (SubArch == SuperHSubArch_4)
+      return "sh4eb";
+    if (SubArch == SuperHSubArch_4a)
+      return "sh4aeb";
+    break;
+  case Triple::shel:
+    if (SubArch == SuperHSubArch_1)
+      return "sh1el";
+    if (SubArch == SuperHSubArch_2)
+      return "sh2el";
+    if (SubArch == SuperHSubArch_2a)
+      return "sh2ael";
+    if (SubArch == SuperHSubArch_2e)
+      return "sh2eel";
+    if (SubArch == SuperHSubArch_3)
+      return "sh3el";
+    if (SubArch == SuperHSubArch_3e)
+      return "sh3eel";
+    if (SubArch == SuperHSubArch_4)
+      return "sh4el";
+    if (SubArch == SuperHSubArch_4a)
+      return "sh4ael";
+    break;
   case Triple::spirv:
     switch (SubArch) {
     case Triple::SPIRVSubArch_v10:
@@ -309,6 +346,10 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
   case bpfeb:
     return "bpf";
 
+  case sheb:
+  case shel:
+    return "sh";
+
   case sparcv9:
   case sparcel:
   case sparc:
@@ -458,8 +499,24 @@ static Triple::ArchType parseBPFArch(StringRef ArchName) {
   }
 }
 
+static Triple::ArchType parseSuperHArch(StringRef ArchName) {
+  SuperH::ISAKind ISA = SuperH::parseArchISA(ArchName);
+  if (ISA != SuperH::ISAKind::INVALID) {
+    SuperH::EndianKind ENDIAN = SuperH::parseArchEndian(ArchName);
+    switch(ENDIAN) {
+      default: break;
+      case SuperH::EndianKind::BIG:
+        return Triple::sheb;
+      case SuperH::EndianKind::LITTLE:
+        return Triple::shel;
+    }
+  }
+  return Triple::UnknownArch;
+}
+
 Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
   Triple::ArchType BPFArch(parseBPFArch(Name));
+  Triple::ArchType SHArch(parseSuperHArch(Name));
   return StringSwitch<Triple::ArchType>(Name)
       .Case("aarch64", aarch64)
       .Case("aarch64_be", aarch64_be)
@@ -491,8 +548,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
       .Case("riscv32be", riscv32be)
       .Case("riscv64be", riscv64be)
       .Case("hexagon", hexagon)
-      .Case("sh", sh)
-      .Case("shl", shl)
+      .StartsWith("sh", SHArch)
       .Case("sparc", sparc)
       .Case("sparcel", sparcel)
       .Case("sparcv9", sparcv9)
@@ -648,8 +704,6 @@ Triple::ArchType Triple::parseArch(StringRef ArchName) {
           .Case("riscv64be", Triple::riscv64be)
           .Case("hexagon", Triple::hexagon)
           .Cases({"s390x", "systemz"}, Triple::systemz)
-          .Case("sh", Triple::sh)
-          .Case("shl", Triple::shl)
           .Case("sparc", Triple::sparc)
           .Case("sparcel", Triple::sparcel)
           .Cases({"sparcv9", "sparc64"}, Triple::sparcv9)
@@ -698,6 +752,8 @@ Triple::ArchType Triple::parseArch(StringRef ArchName) {
       return parseARMArch(ArchName);
     if (ArchName.starts_with("bpf"))
       return parseBPFArch(ArchName);
+    if (ArchName.starts_with("sh"))
+      return parseSuperHArch(ArchName);
   }
 
   return AT;
@@ -859,6 +915,30 @@ Triple::SubArchType Triple::parseSubArch(StringRef SubArchName) {
         .Default(Triple::NoSubArch);
   }
 
+  // SuperH sub arch.
+  if (SubArchName.starts_with("sh")) {
+    switch(SuperH::parseArchISA(SubArchName)) {
+    case SuperH::ISAKind::SH1:
+      return Triple::SuperHSubArch_1;
+    case SuperH::ISAKind::SH2:
+      return Triple::SuperHSubArch_2;
+    case SuperH::ISAKind::SH2A:
+      return Triple::SuperHSubArch_2a;
+    case SuperH::ISAKind::SH2E:
+      return Triple::SuperHSubArch_2e;
+    case SuperH::ISAKind::SH3:
+      return Triple::SuperHSubArch_3;
+    case SuperH::ISAKind::SH3E:
+      return Triple::SuperHSubArch_3e;
+    case SuperH::ISAKind::SH4:
+      return Triple::SuperHSubArch_4;
+    case SuperH::ISAKind::SH4A:
+      return Triple::SuperHSubArch_4a;
+    default:
+      return Triple::NoSubArch;
+    }
+  }
+
   StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName);
 
   // For now, this is the small part. Early return.
@@ -1003,8 +1083,8 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
   case Triple::riscv64:
   case Triple::riscv32be:
   case Triple::riscv64be:
-  case Triple::sh:
-  case Triple::shl:
+  case Triple::sheb:
+  case Triple::shel:
   case Triple::shave:
   case Triple::sparc:
   case Triple::sparcel:
@@ -1771,8 +1851,8 @@ 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::shl:
+  case llvm::Triple::sheb:
+  case llvm::Triple::shel:
   case llvm::Triple::shave:
   case llvm::Triple::sparc:
   case llvm::Triple::sparcel:
@@ -1884,8 +1964,8 @@ Triple Triple::get32BitArchVariant() const {
   case Triple::renderscript32:
   case Triple::riscv32:
   case Triple::riscv32be:
-  case Triple::sh:
-  case Triple::shl:
+  case Triple::sheb:
+  case Triple::shel:
   case Triple::shave:
   case Triple::sparc:
   case Triple::sparcel:
@@ -1978,8 +2058,8 @@ Triple Triple::get64BitArchVariant() const {
   case Triple::m68k:
   case Triple::msp430:
   case Triple::r600:
-  case Triple::sh:
-  case Triple::shl:
+  case Triple::sheb:
+  case Triple::shel:
   case Triple::shave:
   case Triple::sparcel:
   case Triple::tce:
@@ -2160,8 +2240,8 @@ Triple Triple::getBigEndianArchVariant() const {
   case Triple::sparcel:
     T.setArch(Triple::sparc);
     break;
-  case Triple::shl:
-    T.setArch(Triple::sh);
+  case Triple::shel:
+    T.setArch(Triple::sheb);
     break;
   case Triple::tcele:
     T.setArch(Triple::tce);
@@ -2218,8 +2298,8 @@ Triple Triple::getLittleEndianArchVariant() const {
   case Triple::sparc:
     T.setArch(Triple::sparcel);
     break;
-  case Triple::sh:
-    T.setArch(Triple::shl);
+  case Triple::sheb:
+    T.setArch(Triple::shel);
     break;
   case Triple::tce:
     T.setArch(Triple::tcele);
@@ -2261,7 +2341,7 @@ bool Triple::isLittleEndian() const {
   case Triple::riscv32:
   case Triple::riscv64:
   case Triple::shave:
-  case Triple::shl:
+  case Triple::shel:
   case Triple::sparcel:
   case Triple::spir64:
   case Triple::spir:

>From 6a71af5b9aecd1345c43defd6c23f836ef2b6928 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 24 Sep 2026 22:53:38 +0200
Subject: [PATCH 53/67] Fix non-clang host compiler compat

---
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 10 ----------
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  4 ++--
 2 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index cc0cfff092cb3..248bd7c0d2bb5 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -41,9 +41,6 @@ using namespace llvm;
 
 #define DEBUG_TYPE "sh-lower"
 
-#define DEBUG_FN_PRINT()                                                       \
-  LLVM_DEBUG(dbgs() << " - " << __PRETTY_FUNCTION__ << "\n");
-
 SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
                                            const SuperHSubtarget &STI)
     : TargetLowering(TM, STI), Subtarget(&STI) {
@@ -273,7 +270,6 @@ SDValue SuperHTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
 }
 
 SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
-  DEBUG_FN_PRINT()
 
   SDValue Chain = Op.getOperand(0);
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
@@ -299,7 +295,6 @@ SDValue SuperHTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
 void SuperHTargetLowering::ReplaceNodeResults(SDNode *N,
                                               SmallVectorImpl<SDValue> &Results,
                                               SelectionDAG &DAG) const {
-  DEBUG_FN_PRINT()
 
   SDLoc DL(N);
 
@@ -330,7 +325,6 @@ void SuperHTargetLowering::ReplaceNodeResults(SDNode *N,
 
 SDValue SuperHTargetLowering::LowerConstant(SDValue Op,
                                             SelectionDAG &DAG) const {
-  DEBUG_FN_PRINT()
 
   // Get the address of the target into a register
   if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
@@ -358,7 +352,6 @@ SDValue SuperHTargetLowering::LowerConstant(SDValue Op,
 
 SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op,
                                                  SelectionDAG &DAG) const {
-  DEBUG_FN_PRINT()
 
   // Get the address of the target into a register
   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Op)) {
@@ -375,7 +368,6 @@ SDValue SuperHTargetLowering::LowerGlobalAddress(SDValue Op,
 
 SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op,
                                                   SelectionDAG &DAG) const {
-  DEBUG_FN_PRINT()
 
   // Get the address of the target into a register
   if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Op)) {
@@ -394,7 +386,6 @@ SDValue SuperHTargetLowering::LowerExternalSymbol(SDValue Op,
 
 SDValue SuperHTargetLowering::LowerBlockAddress(SDValue Op,
                                                 SelectionDAG &DAG) const {
-  DEBUG_FN_PRINT()
 
   // Get the address of the target into a register
   if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) {
@@ -975,7 +966,6 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op,
 MachineBasicBlock *
 SuperHTargetLowering::insertSELECTCC(MachineInstr &MI,
                                      MachineBasicBlock *MBB) const {
-  DEBUG_FN_PRINT()
 
   MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
   const SuperHInstrInfo &TII = *Subtarget->getInstrInfo();
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 4d9ca9efa7bd3..d9c80b3dbfa55 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -192,7 +192,7 @@ void SuperHInstrInfo::storeRegToStackSlot(
     MachineInstr::MIFlag Flags) const {
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  uint ObjectSize = MFI.getObjectSize(FrameIndex);
+  uint64_t ObjectSize = MFI.getObjectSize(FrameIndex);
 
   LLVM_DEBUG(dbgs() << "Store "
                     << (SrcReg > RI.getNumRegs() ? "VREG" : RI.getName(SrcReg))
@@ -237,7 +237,7 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
                                            MachineInstr::MIFlag Flags) const {
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  uint ObjectSize = MFI.getObjectSize(FrameIndex);
+  uint64_t ObjectSize = MFI.getObjectSize(FrameIndex);
 
   LLVM_DEBUG(
       dbgs() << "Load "

>From 35b6ebea65fcded6b4e86bf259031c009c5038c9 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 24 Sep 2026 23:34:43 +0200
Subject: [PATCH 54/67] Fix GT condition codes for non-const comparison

---
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 248bd7c0d2bb5..85e09cb90d96a 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -199,6 +199,8 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
       }
       }
     }
+    SHcc = SHCC::COND_GT;
+    SHocc = SHCC::COND_T;
     break;
   }
   case ISD::SETGE: {

>From 1c361b8ebebb493b64a3bd449018f61ea05efaee Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 24 Sep 2026 23:35:00 +0200
Subject: [PATCH 55/67] Fix SelectAddr against SHISD::WRAPPER

---
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 46 ++++++++++---------
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 070e9ca6ceec1..3e41a19329137 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -119,33 +119,37 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
     return true;
   }
 
-  if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
-
-    // Handle frame index + offset
-    if (N.getOperand(0).getOpcode() == ISD::FrameIndex) {
-      int RHSC = (int)RHS->getZExtValue();
-      int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
-
-      Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
-      Disp = CurDAG->getTargetConstant(RHSC, SDLoc(Op), MVT::i32);
-      return true;
-    }
-
-    // Handle reg + offset
-    if (N.getOpcode() == ISD::ADD) {
-      Base = N.getOperand(0);
-      Disp =
-          CurDAG->getTargetConstant(RHS->getZExtValue(), SDLoc(Op), MVT::i32);
-      return true;
-    }
-  }
-
   // if the address is a wrapper, get the underlying data.
   if (N.getOpcode() == SHISD::WRAPPER) {
     Base = N.getOperand(0);
     Disp = N;
     return true;
   }
+
+  // Constant displacements has more operands, if there's 2 or more, assume
+  // the address may be a form of displacement.
+  if (N.getNumOperands() >= 2) { 
+    if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+
+      // Handle frame index + offset
+      if (N.getOperand(0).getOpcode() == ISD::FrameIndex) {
+        int RHSC = (int)RHS->getZExtValue();
+        int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
+
+        Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
+        Disp = CurDAG->getTargetConstant(RHSC, SDLoc(Op), MVT::i32);
+        return true;
+      }
+
+      // Handle reg + offset
+      if (N.getOpcode() == ISD::ADD) {
+        Base = N.getOperand(0);
+        Disp =
+            CurDAG->getTargetConstant(RHS->getZExtValue(), SDLoc(Op), MVT::i32);
+        return true;
+      }
+    }
+  }
   return false;
 }
 

>From 73c1575bf947b2c9416ee5690b8a07c7cdcb4bd8 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Thu, 24 Sep 2026 23:59:53 +0200
Subject: [PATCH 56/67] Fix loads/stores w/ address-in-register

---
 llvm/lib/Target/SuperH/SuperHInstrInfo.td | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 7b64a55e56cf3..ff7bd933b6407 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -1587,4 +1587,13 @@ def : Pat<(i32 (sextloadi16 addr:$src)),        (EXTSW (MOVWLPtr addr:$src))>;
 def : Pat<(i32 (load        addr:$src)),               (MOVLLPtr addr:$src)>;
 def : Pat<(i32 (zextloadi1  addr:$src)),        (EXTUB (MOVBLPtr addr:$src))>;
 def : Pat<(i32 (zextloadi8  addr:$src)),        (EXTUB (MOVBLPtr addr:$src))>;
-def : Pat<(i32 (zextloadi16 addr:$src)),        (EXTUW (MOVWLPtr addr:$src))>;
\ No newline at end of file
+def : Pat<(i32 (zextloadi16 addr:$src)),        (EXTUW (MOVWLPtr addr:$src))>;
+def : Pat<(i32 (load         i32:$src)),               (MOVLL i32:$src)>;
+def : Pat<(i32 (zextloadi1   i32:$src)),        (EXTUB (MOVBL i32:$src))>;
+def : Pat<(i32 (zextloadi8   i32:$src)),        (EXTUB (MOVBL i32:$src))>;
+def : Pat<(i32 (zextloadi16  i32:$src)),        (EXTUW (MOVWL i32:$src))>;
+
+//===--------------------------------------------------------------------------===//
+// Stores
+//===--------------------------------------------------------------------------===//
+def : Pat<(store    i32:$src, i32:$dst),        (MOVLS i32:$src, i32:$dst)>;
\ No newline at end of file

>From 016c0a837371c9b765f35c37c8d95a20b278a444 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 25 Sep 2026 00:22:52 +0200
Subject: [PATCH 57/67] Further fixes to load/store handling

---
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 14 --------------
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  4 +++-
 2 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 85e09cb90d96a..3a60b4bf99d1f 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -87,22 +87,14 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
   setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
 
-  for (MVT VT : MVT::integer_valuetypes()) {
-    setOperationAction(ISD::Constant, VT, Custom);
-  }
-
   setOperationAction(ISD::BR_CC, MVT::i8, Custom);
   setOperationAction(ISD::BR_CC, MVT::i16, Custom);
   setOperationAction(ISD::BR_CC, MVT::i32, Custom);
   setOperationAction(ISD::BR_CC, MVT::i64, Custom);
   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
 
-  setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
-  setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
-  setOperationAction(ISD::SETCC, MVT::i8, Custom);
-  setOperationAction(ISD::SETCC, MVT::i16, Custom);
   setOperationAction(ISD::SETCC, MVT::i32, Custom);
   setOperationAction(ISD::SETCC, MVT::i64, Custom);
 
@@ -301,12 +293,6 @@ void SuperHTargetLowering::ReplaceNodeResults(SDNode *N,
   SDLoc DL(N);
 
   switch (N->getOpcode()) {
-  case ISD::Constant: {
-    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
-      Results.push_back(DAG.getConstant(C->getSExtValue(), DL, MVT::i32));
-    }
-    break;
-  }
   default: {
     SDValue Res = LowerOperation(SDValue(N, 0), DAG);
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index ff7bd933b6407..2225ce38fa3d4 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -1584,11 +1584,13 @@ def : Pat<(i32 (load        addr:$src)),               (MOVLLPtr addr:$src)>;
 def : Pat<(i32 (sextloadi1  addr:$src)), (EXTSB (EXTUB (MOVBLPtr addr:$src)))>;
 def : Pat<(i32 (sextloadi8  addr:$src)), (EXTSB (EXTUB (MOVBLPtr addr:$src)))>;
 def : Pat<(i32 (sextloadi16 addr:$src)),        (EXTSW (MOVWLPtr addr:$src))>;
-def : Pat<(i32 (load        addr:$src)),               (MOVLLPtr addr:$src)>;
 def : Pat<(i32 (zextloadi1  addr:$src)),        (EXTUB (MOVBLPtr addr:$src))>;
 def : Pat<(i32 (zextloadi8  addr:$src)),        (EXTUB (MOVBLPtr addr:$src))>;
 def : Pat<(i32 (zextloadi16 addr:$src)),        (EXTUW (MOVWLPtr addr:$src))>;
 def : Pat<(i32 (load         i32:$src)),               (MOVLL i32:$src)>;
+def : Pat<(i32 (sextloadi1   i32:$src)), (EXTSB (EXTUB (MOVBL i32:$src)))>;
+def : Pat<(i32 (sextloadi8   i32:$src)), (EXTSB (EXTUB (MOVBL i32:$src)))>;
+def : Pat<(i32 (sextloadi16  i32:$src)),        (EXTSW (MOVWL i32:$src))>;
 def : Pat<(i32 (zextloadi1   i32:$src)),        (EXTUB (MOVBL i32:$src))>;
 def : Pat<(i32 (zextloadi8   i32:$src)),        (EXTUB (MOVBL i32:$src))>;
 def : Pat<(i32 (zextloadi16  i32:$src)),        (EXTUW (MOVWL i32:$src))>;

>From 2bb53729164100a144743c51c503fce320dad02e Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Fri, 25 Sep 2026 23:18:54 +0200
Subject: [PATCH 58/67] Lower immediate addresses to constpool

Also separates operands that target addresses vs frame indices.
---
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 190 ++++++++++--------
 .../lib/Target/SuperH/SuperHFrameLowering.cpp |   9 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  47 +++--
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp |   5 +
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  14 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     | 109 +++++++---
 6 files changed, 241 insertions(+), 133 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index 225fb7fd7f176..5e47da6372fff 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -62,9 +62,9 @@ class SuperHExpandPseudo : public MachineFunctionPass {
   template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
 
   bool storeToFrame(Block &MBB, BlockIt MBBI, int Scale);
-  bool storeToGlobal(Block &MBB, BlockIt MBBI);
+  bool storeToAddress(Block &MBB, BlockIt MBBI);
   bool loadFromFrame(Block &MBB, BlockIt MBBI, int Scale);
-  bool loadFromGlobal(Block &MBB, BlockIt MBBI);
+  bool loadFromAddress(Block &MBB, BlockIt MBBI);
 };
 
 
@@ -129,7 +129,7 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
   switch (MI.getOpcode()) {
   default:
     llvm_unreachable("Expected valid MOV*SPtr opcode.");
-  case SH::MOVBSPtr: {
+  case SH::MOVBSF: {
 
     // mov      <src reg>,  r0
     // mov.b    r0, @(offset,r1)
@@ -140,7 +140,7 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
         .addImm(Offset);
     break;
   }
-  case SH::MOVWSPtr: {
+  case SH::MOVWSF: {
 
     // mov      <src reg>,  r0
     // mov.w    r0, @(offset,r1)
@@ -151,7 +151,7 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
         .addImm(Offset);
     break;
   }
-  case SH::MOVLSPtr: {
+  case SH::MOVLSF: {
 
     // mov.b    <src reg>, @(offset,r1)
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
@@ -165,33 +165,38 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
   return eraseMI(MI);
 }
 
-bool SuperHExpandPseudo::storeToGlobal(Block &MBB, BlockIt MBBI) {
+bool SuperHExpandPseudo::storeToAddress(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
   const SuperHMachineFunctionInfo *FI = MF.getInfo<SuperHMachineFunctionInfo>();
 
-  auto SrcReg = MI.getOperand(0).getReg();
-  auto *G = FI->tryGetConstant(MI.getOperand(1).getGlobal(), MF);
-  if (!G)
-    return false;
+  Register SrcReg = MI.getOperand(0).getReg();
+  Register DstReg;
 
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
-      .addConstantPoolIndex(G->getLabelId());
+  if (MI.getOperand(1).isGlobal()) {
+    if (auto *G = FI->tryGetConstant(MI.getOperand(1).getGlobal(), MF)) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
+          .addConstantPoolIndex(G->getLabelId());
+      DstReg = SH::R1;
+    }
+  } else if (MI.getOperand(1).isReg()) {
+    DstReg = MI.getOperand(1).getReg();
+  }
 
   switch (MI.getOpcode()) {
   default:
     llvm_unreachable("Expected valid MOV*SPtr opcode.");
-  case SH::MOVBSPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS)).addReg(SrcReg).addReg(SH::R1);
+  case SH::MOVBSP: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS)).addReg(SrcReg).addReg(DstReg);
     break;
   }
-  case SH::MOVWSPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS)).addReg(SrcReg).addReg(SH::R1);
+  case SH::MOVWSP: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS)).addReg(SrcReg).addReg(DstReg);
     break;
   }
-  case SH::MOVLSPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS)).addReg(SrcReg).addReg(SH::R1);
+  case SH::MOVLSP: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS)).addReg(SrcReg).addReg(DstReg);
     break;
   }
   }
@@ -200,41 +205,47 @@ bool SuperHExpandPseudo::storeToGlobal(Block &MBB, BlockIt MBBI) {
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVBSPtr>(Block &MBB, BlockIt MBBI) {
-  MachineInstr &MI = *MBBI;
-
-  // Store to global.
-  if (MI.getOperand(1).isGlobal()) {
-    return storeToGlobal(MBB, MBBI);
-  }
+bool SuperHExpandPseudo::expand<SH::MOVBSF>(Block &MBB, BlockIt MBBI) {
 
+  // Store to stack frame
   return storeToFrame(MBB, MBBI, 1);
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVWSPtr>(Block &MBB, BlockIt MBBI) {
-  MachineInstr &MI = *MBBI;
-
-  // Store to global.
-  if (MI.getOperand(1).isGlobal()) {
-    return storeToGlobal(MBB, MBBI);
-  }
+bool SuperHExpandPseudo::expand<SH::MOVWSF>(Block &MBB, BlockIt MBBI) {
 
+  // Store to stack frame
   return storeToFrame(MBB, MBBI, 2);
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVLSPtr>(Block &MBB, BlockIt MBBI) {
-  MachineInstr &MI = *MBBI;
-
-  // Store to global.
-  if (MI.getOperand(1).isGlobal()) {
-    return storeToGlobal(MBB, MBBI);
-  }
+bool SuperHExpandPseudo::expand<SH::MOVLSF>(Block &MBB, BlockIt MBBI) {
 
+  // Store to stack frame
   return storeToFrame(MBB, MBBI, 4);
 }
 
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVBSP>(Block &MBB, BlockIt MBBI) {
+  
+  // Store to address.
+  return storeToAddress(MBB, MBBI);
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVWSP>(Block &MBB, BlockIt MBBI) {
+
+  // Store to address.
+  return storeToAddress(MBB, MBBI);
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVLSP>(Block &MBB, BlockIt MBBI) {
+
+  // Store to address.
+  return storeToAddress(MBB, MBBI);
+}
+
 
 
 
@@ -264,7 +275,7 @@ bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
   switch (MI.getOpcode()) {
   default:
     llvm_unreachable("Expected valid MOV*LPtr opcode.");
-  case SH::MOVBLPtr: {
+  case SH::MOVBLF: {
 
     // mov.w    @(offset,r1), r0
     // mov      r0,           <dst reg>
@@ -277,7 +288,7 @@ bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
         .addReg(SH::R0, RegState::Kill);
     break;
   }
-  case SH::MOVWLPtr: {
+  case SH::MOVWLF: {
 
     // mov.b    @(offset,r1), r0
     // mov      r0,           <dst reg>
@@ -287,7 +298,7 @@ bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
         .addReg(SH::R0, RegState::Define);
     break;
   }
-  case SH::MOVLLPtr: {
+  case SH::MOVLLF: {
 
     // mov.l    @(offset,r1), <dst reg>
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL4))
@@ -301,34 +312,38 @@ bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
   return eraseMI(MI);
 }
 
-bool SuperHExpandPseudo::loadFromGlobal(Block &MBB, BlockIt MBBI) {
+bool SuperHExpandPseudo::loadFromAddress(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
   const MachineFunction &MF = *MBB.getParent();
   const SuperHMachineFunctionInfo *FI = MF.getInfo<SuperHMachineFunctionInfo>();
 
-  auto DstReg = MI.getOperand(0).getReg();
-  auto *G = FI->tryGetConstant(MI.getOperand(1).getGlobal(), MF);
+  Register DstReg = MI.getOperand(0).getReg();
+  Register SrcReg;
 
-  if (!G)
-    return false;
-
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
-      .addConstantPoolIndex(G->getLabelId());
+  if (MI.getOperand(1).isGlobal()) {
+    if (auto *G = FI->tryGetConstant(MI.getOperand(1).getGlobal(), MF)) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
+          .addConstantPoolIndex(G->getLabelId());
+      SrcReg = SH::R1;
+    }
+  } else if (MI.getOperand(1).isReg()) {
+    SrcReg = MI.getOperand(1).getReg();
+  }
 
   switch (MI.getOpcode()) {
   default:
     llvm_unreachable("Expected valid MOV*LPtr opcode.");
-  case SH::MOVBLPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL), DstReg).addReg(SH::R1);
+  case SH::MOVBLP: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL), DstReg).addReg(SrcReg);
     break;
   }
-  case SH::MOVWLPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL), DstReg).addReg(SH::R1);
+  case SH::MOVWLP: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL), DstReg).addReg(SrcReg);
     break;
   }
-  case SH::MOVLLPtr: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL), DstReg).addReg(SH::R1);
+  case SH::MOVLLP: {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL), DstReg).addReg(SrcReg);
     break;
   }
   }
@@ -337,38 +352,47 @@ bool SuperHExpandPseudo::loadFromGlobal(Block &MBB, BlockIt MBBI) {
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVBLPtr>(Block &MBB, BlockIt MBBI) {
-  MachineInstr &MI = *MBBI;
-
-  // Load from global.
-  if (MI.getOperand(1).isGlobal())
-    return loadFromGlobal(MBB, MBBI);
+bool SuperHExpandPseudo::expand<SH::MOVBLF>(Block &MBB, BlockIt MBBI) {
 
+  // Load from stack frame.
   return loadFromFrame(MBB, MBBI, 1);
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVWLPtr>(Block &MBB, BlockIt MBBI) {
-  MachineInstr &MI = *MBBI;
-
-  // Load from global.
-  if (MI.getOperand(1).isGlobal())
-    return loadFromGlobal(MBB, MBBI);
+bool SuperHExpandPseudo::expand<SH::MOVWLF>(Block &MBB, BlockIt MBBI) {
 
+  // Load from stack frame.
   return loadFromFrame(MBB, MBBI, 2);
 }
 
 template <>
-bool SuperHExpandPseudo::expand<SH::MOVLLPtr>(Block &MBB, BlockIt MBBI) {
-  MachineInstr &MI = *MBBI;
-
-  // Load from global.
-  if (MI.getOperand(1).isGlobal())
-    return loadFromGlobal(MBB, MBBI);
+bool SuperHExpandPseudo::expand<SH::MOVLLF>(Block &MBB, BlockIt MBBI) {
 
+  // Load from stack frame.
   return loadFromFrame(MBB, MBBI, 4);
 }
 
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVBLP>(Block &MBB, BlockIt MBBI) {
+
+  // Load from address.
+  return loadFromAddress(MBB, MBBI);
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVWLP>(Block &MBB, BlockIt MBBI) {
+
+  // Load from address.
+  return loadFromAddress(MBB, MBBI);
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVLLP>(Block &MBB, BlockIt MBBI) {
+
+  // Load from address.
+  return loadFromAddress(MBB, MBBI);
+}
+
 
 
 
@@ -603,12 +627,18 @@ bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
   switch (Opcode) {
   default:
     break;
-    EXPAND(SH::MOVBSPtr);
-    EXPAND(SH::MOVWSPtr);
-    EXPAND(SH::MOVLSPtr);
-    EXPAND(SH::MOVBLPtr);
-    EXPAND(SH::MOVWLPtr);
-    EXPAND(SH::MOVLLPtr);
+    EXPAND(SH::MOVBSF);
+    EXPAND(SH::MOVWSF);
+    EXPAND(SH::MOVLSF);
+    EXPAND(SH::MOVBLF);
+    EXPAND(SH::MOVWLF);
+    EXPAND(SH::MOVLLF);
+    EXPAND(SH::MOVBSP);
+    EXPAND(SH::MOVWSP);
+    EXPAND(SH::MOVLSP);
+    EXPAND(SH::MOVBLP);
+    EXPAND(SH::MOVWLP);
+    EXPAND(SH::MOVLLP);
     EXPAND(SH::SHLri);
     EXPAND(SH::SHRri);
     EXPAND(SH::SRAri);
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 86a923fb9c48d..4d899c91c3d8a 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -401,9 +401,12 @@ struct SuperHFrameFixupPass : public MachineFunctionPass {
       BlockIt NII = std::next(II);
 
       switch (II->getOpcode()) {
-      case SH::MOVBLPtr:
-      case SH::MOVWLPtr:
-      case SH::MOVLLPtr:
+      case SH::MOVBLF:
+      case SH::MOVWLF:
+      case SH::MOVLLF:
+      case SH::MOVBLP:
+      case SH::MOVWLP:
+      case SH::MOVLLP:
       case SH::ADJCALLSTACKUP:
       case SH::NOP: {
         break;
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 3e41a19329137..f16b9ddf4d9f6 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -53,6 +53,7 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
                                     std::vector<SDValue> &OutOps) override;
 
   bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
+  bool SelectFrAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
 
   /// Return a target constant with the specified value of type i4.
   inline SDValue getI4Imm(int64_t Imm, const SDLoc &DL) {
@@ -101,28 +102,29 @@ bool SuperHDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
   return SelectionDAGISel::runOnMachineFunction(MF);
 }
 
+
+
+
+//===----------------------------------------------------------------------===//
+//                             Operand Selection
+//===----------------------------------------------------------------------===//
+
 bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(
     const SDValue &Op, InlineAsm::ConstraintCode ConstraintCode,
     std::vector<SDValue> &OutOps) {
   return false;
 }
 
+// Selects non-frame address operands.
 bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
                                     SDValue &Disp) {
   auto DL = CurDAG->getDataLayout();
   MVT PtrVT = getTargetLowering()->getPointerTy(DL);
 
-  // if the address is a frame index get the TargetFrameIndex.
-  if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
-    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
-    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
-    return true;
-  }
-
   // if the address is a wrapper, get the underlying data.
   if (N.getOpcode() == SHISD::WRAPPER) {
-    Base = N.getOperand(0);
-    Disp = N;
+    Base = N;
+    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32);
     return true;
   }
 
@@ -153,6 +155,22 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
   return false;
 }
 
+// Selects frame address operands.
+bool SuperHDAGToDAGISel::SelectFrAddr(SDNode *Op, SDValue N, SDValue &Base,
+                                    SDValue &Disp) {
+  auto DL = CurDAG->getDataLayout();
+  MVT PtrVT = getTargetLowering()->getPointerTy(DL);
+
+  // if the address is a frame index get the TargetFrameIndex.
+  if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
+    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
+    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32);
+    return true;
+  }
+
+  return false;
+}
+
 
 
 
@@ -189,8 +207,9 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
     }
   }
 
-  if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
-    if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
+  // Global Addresses
+  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(GA, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
       ReplaceNode(N, Res);
@@ -198,9 +217,9 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
     }
   }
 
-  // Global Addresses
-  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N0.getNode())) {
-    if (auto *CPV = SFI->tryGetConstant(GA, *CurDAG, SHCP::no_modifier)) {
+  // Constants
+  if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
       MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, DL, MVT::i32, TGA);
       ReplaceNode(N, Res);
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 3a60b4bf99d1f..8c6e40b2cb945 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -82,6 +82,11 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::MUL, VT, Custom);
   }
 
+  // Constants have special lowering rules depending on their length.
+  for (MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64}) {
+    setOperationAction(ISD::Constant, VT, Custom);
+  }
+
   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
   setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index d9c80b3dbfa55..2ba57525a55fd 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -178,6 +178,7 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 
 Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
                                              int &FrameIndex) const {
+  dbgs() << "isStoreToStackSlot\n";
   if (MI.getOperand(0).isReg() && MI.getOperand(1).isFI() &&
       MI.getOperand(2).getImm() == 0) {
     FrameIndex = MI.getOperand(1).getIndex();
@@ -204,13 +205,13 @@ void SuperHInstrInfo::storeRegToStackSlot(
   default:
     llvm_unreachable("Cannot store this register into stack slot!");
   case 1:
-    Opc = SH::MOVBSPtr;
+    Opc = SH::MOVBSF;
     break;
   case 2:
-    Opc = SH::MOVWSPtr;
+    Opc = SH::MOVWSF;
     break;
   case 4:
-    Opc = SH::MOVLSPtr;
+    Opc = SH::MOVLSF;
     break;
   }
   BuildMI(MBB, II, DebugLoc(), get(Opc))
@@ -221,6 +222,7 @@ void SuperHInstrInfo::storeRegToStackSlot(
 
 Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
                                               int &FrameIndex) const {
+  dbgs() << "isLoadFromStackSlot\n";
   if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
       MI.getOperand(1).getImm() == 0) {
     FrameIndex = MI.getOperand(0).getIndex();
@@ -249,13 +251,13 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
   default:
     llvm_unreachable("Cannot load this register from stack slot!");
   case 1:
-    Opc = SH::MOVBLPtr;
+    Opc = SH::MOVBLF;
     break;
   case 2:
-    Opc = SH::MOVWLPtr;
+    Opc = SH::MOVWLF;
     break;
   case 4:
-    Opc = SH::MOVLLPtr;
+    Opc = SH::MOVLLF;
     break;
   }
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 2225ce38fa3d4..9014ed43ad4a6 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -235,6 +235,10 @@ def IGPRDec : SHIndirectRegOp<GPR, "Dec">;
 let WantsRoot = true in
 def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
 
+// Addressing mode pattern reg+disp (Frame)
+let WantsRoot = true in
+def fraddr : ComplexPattern<iPTR, 2, "SelectFrAddr">;
+
 
 
 
@@ -1449,43 +1453,75 @@ def Select32    : SHSelectPseudo<(outs GPR:$dst),
 // Frame Load/Store
 //===--------------------------------------------------------------------------===//
 
-// LOAD FROM ADDRESS
 let mayLoad = 1, isReMaterializable = 1 in {
 
+// LOAD FROM ADDRESS
 let Defs = [R0, R1] in
-def MOVBLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
-                            "! MOVBLPtr $src, $Rn",
+def MOVBLP    : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVBLP $src, $Rn",
                             []>;
 
 let Defs = [R0, R1] in
-def MOVWLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
-                            "! MOVWLPtr $src, $Rn",
+def MOVWLP    : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVWLP $src, $Rn",
                             []>;
 
 let Defs = [R1] in
-def MOVLLPtr  : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
-                            "! MOVLLPtr $src, $Rn",
+def MOVLLP    : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVLLP $src, $Rn",
+                            []>;
+
+// LOAD FROM FRAME
+let Defs = [R0, R1] in
+def MOVBLF    : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVBLF $src, $Rn",
+                            []>;
+
+let Defs = [R0, R1] in
+def MOVWLF    : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVWLF $src, $Rn",
+                            []>;
+
+let Defs = [R1] in
+def MOVLLF    : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVLLF $src, $Rn",
                             []>;
 }
 
-// STORE TO ADDRESS
 let mayStore = 1, isReMaterializable = 1 in {
 
+// STORE TO ADDRESS
 let Defs = [R0, R1] in
-def MOVBSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
-                             "! MOVBSPtr $src, $dst",
-                             [(truncstorei8 i32:$src, addr:$dst)]>;
+def MOVBSP    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVBSP $src, $dst",
+                             []>;
 
 let Defs = [R0, R1] in
-def MOVWSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
-                             "! MOVWSPtr $src, $dst",
+def MOVWSP    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVWSP $src, $dst",
                              [(truncstorei16 i32:$src, addr:$dst)]>;
 
 let Defs = [R1] in
-def MOVLSPtr  : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
-                             "! MOVLSPtr $src, $dst",
+def MOVLSP    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVLSP $src, $dst",
                              [(store i32:$src, addr:$dst)]>;
 
+// STORE TO FRAME
+let Defs = [R0, R1] in
+def MOVBSF    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVBSF $src, $dst",
+                             []>;
+
+let Defs = [R0, R1] in
+def MOVWSF    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVWSF $src, $dst",
+                             []>;
+
+let Defs = [R1] in
+def MOVLSF    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
+                             "! MOVLSF $src, $dst",
+                             []>;
+
 }
 
 
@@ -1580,22 +1616,35 @@ def : Pat<(i32 (sra i32:$src1, i32:$src2)),         (SRArr GPR:$src1, GPR:$src2)
 // Loads
 //===--------------------------------------------------------------------------===//
 
-def : Pat<(i32 (load        addr:$src)),               (MOVLLPtr addr:$src)>;
-def : Pat<(i32 (sextloadi1  addr:$src)), (EXTSB (EXTUB (MOVBLPtr addr:$src)))>;
-def : Pat<(i32 (sextloadi8  addr:$src)), (EXTSB (EXTUB (MOVBLPtr addr:$src)))>;
-def : Pat<(i32 (sextloadi16 addr:$src)),        (EXTSW (MOVWLPtr addr:$src))>;
-def : Pat<(i32 (zextloadi1  addr:$src)),        (EXTUB (MOVBLPtr addr:$src))>;
-def : Pat<(i32 (zextloadi8  addr:$src)),        (EXTUB (MOVBLPtr addr:$src))>;
-def : Pat<(i32 (zextloadi16 addr:$src)),        (EXTUW (MOVWLPtr addr:$src))>;
-def : Pat<(i32 (load         i32:$src)),               (MOVLL i32:$src)>;
-def : Pat<(i32 (sextloadi1   i32:$src)), (EXTSB (EXTUB (MOVBL i32:$src)))>;
-def : Pat<(i32 (sextloadi8   i32:$src)), (EXTSB (EXTUB (MOVBL i32:$src)))>;
-def : Pat<(i32 (sextloadi16  i32:$src)),        (EXTSW (MOVWL i32:$src))>;
-def : Pat<(i32 (zextloadi1   i32:$src)),        (EXTUB (MOVBL i32:$src))>;
-def : Pat<(i32 (zextloadi8   i32:$src)),        (EXTUB (MOVBL i32:$src))>;
-def : Pat<(i32 (zextloadi16  i32:$src)),        (EXTUW (MOVWL i32:$src))>;
+def : Pat<(i32 (load          addr:$src)),               (MOVLLP   addr:$src)>;
+def : Pat<(i32 (sextloadi1    addr:$src)), (EXTSB (EXTUB (MOVBLP   addr:$src)))>;
+def : Pat<(i32 (sextloadi8    addr:$src)), (EXTSB (EXTUB (MOVBLP   addr:$src)))>;
+def : Pat<(i32 (sextloadi16   addr:$src)),        (EXTSW (MOVWLP   addr:$src))>;
+def : Pat<(i32 (zextloadi1    addr:$src)),        (EXTUB (MOVBLP   addr:$src))>;
+def : Pat<(i32 (zextloadi8    addr:$src)),        (EXTUB (MOVBLP   addr:$src))>;
+def : Pat<(i32 (zextloadi16   addr:$src)),        (EXTUW (MOVWLP   addr:$src))>;
+def : Pat<(i32 (load        fraddr:$src)),               (MOVLLF fraddr:$src)>;
+def : Pat<(i32 (sextloadi1  fraddr:$src)), (EXTSB (EXTUB (MOVBLF fraddr:$src)))>;
+def : Pat<(i32 (sextloadi8  fraddr:$src)), (EXTSB (EXTUB (MOVBLF fraddr:$src)))>;
+def : Pat<(i32 (sextloadi16 fraddr:$src)),        (EXTSW (MOVWLF fraddr:$src))>;
+def : Pat<(i32 (zextloadi1  fraddr:$src)),        (EXTUB (MOVBLF fraddr:$src))>;
+def : Pat<(i32 (zextloadi8  fraddr:$src)),        (EXTUB (MOVBLF fraddr:$src))>;
+def : Pat<(i32 (zextloadi16 fraddr:$src)),        (EXTUW (MOVWLF fraddr:$src))>;
+def : Pat<(i32 (load           i32:$src)),               (MOVLL     i32:$src)>;
+def : Pat<(i32 (sextloadi1     i32:$src)), (EXTSB (EXTUB (MOVBL     i32:$src)))>;
+def : Pat<(i32 (sextloadi8     i32:$src)), (EXTSB (EXTUB (MOVBL     i32:$src)))>;
+def : Pat<(i32 (sextloadi16    i32:$src)),        (EXTSW (MOVWL     i32:$src))>;
+def : Pat<(i32 (zextloadi1     i32:$src)),        (EXTUB (MOVBL     i32:$src))>;
+def : Pat<(i32 (zextloadi8     i32:$src)),        (EXTUB (MOVBL     i32:$src))>;
+def : Pat<(i32 (zextloadi16    i32:$src)),        (EXTUW (MOVWL     i32:$src))>;
 
 //===--------------------------------------------------------------------------===//
 // Stores
 //===--------------------------------------------------------------------------===//
-def : Pat<(store    i32:$src, i32:$dst),        (MOVLS i32:$src, i32:$dst)>;
\ No newline at end of file
+def : Pat<(store          i32:$src,    i32:$dst),      (MOVLS   i32:$src,    i32:$dst)>;
+def : Pat<(truncstorei8   i32:$src,   addr:$dst),      (MOVBSP  i32:$src,   addr:$dst)>;
+def : Pat<(truncstorei16  i32:$src,   addr:$dst),      (MOVWSP  i32:$src,   addr:$dst)>;
+def : Pat<(store          i32:$src,   addr:$dst),      (MOVLSP  i32:$src,   addr:$dst)>;
+def : Pat<(truncstorei8   i32:$src, fraddr:$dst),      (MOVBSF  i32:$src, fraddr:$dst)>;
+def : Pat<(truncstorei16  i32:$src, fraddr:$dst),      (MOVWSF  i32:$src, fraddr:$dst)>;
+def : Pat<(store          i32:$src, fraddr:$dst),      (MOVLSF  i32:$src, fraddr:$dst)>;
\ No newline at end of file

>From 4e8f2b17af8c8d6fa4df5cc48fffd82a593fdccf Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 27 Sep 2026 01:06:48 +0200
Subject: [PATCH 59/67] More refactoring

---
 llvm/include/llvm/BinaryFormat/ELF.h          |  26 +++
 .../Target/SuperH/MCTargetDesc/CMakeLists.txt |   1 +
 .../SuperH/MCTargetDesc/SuperHAsmBackend.cpp  |  20 +-
 .../SuperH/MCTargetDesc/SuperHAsmBackend.h    |   3 +-
 .../MCTargetDesc/SuperHMCCodeEmitter.cpp      |  79 +++-----
 .../MCTargetDesc/SuperHTargetStreamer.cpp     |  28 ++-
 .../MCTargetDesc/SuperHTargetStreamer.h       |   7 +
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 179 ++++++++++++------
 .../lib/Target/SuperH/SuperHFrameLowering.cpp |   1 +
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  84 ++++----
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 114 ++++++-----
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    | 173 +++++++++++------
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |  19 ++
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  73 ++++---
 llvm/lib/Target/SuperH/SuperHRegisterInfo.h   |   4 +-
 llvm/lib/TargetParser/SuperHTargetParser.cpp  |   2 +-
 16 files changed, 508 insertions(+), 305 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 48f25d02cb80e..fb21517e49517 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -738,6 +738,32 @@ enum {
 #include "ELFRelocs/SuperH.def"
 };
 
+// SuperH Specific e_flags
+enum : unsigned {
+  EF_SH_MACH_MASK = 0x1f,
+  EF_SH_UNKNOWN = 0x0,
+  EF_SH1 = 0x1,
+  EF_SH2 = 0x2,
+  EF_SH3 = 0x3,
+  EF_SH_DSP = 0x4,
+  EF_SH3_DSP = 0x5,
+  EF_SH4AL_DSP = 0x6,
+  EF_SH3E = 0x8,
+  EF_SH4 = 0x9,
+  EF_SH2E = 0xb,
+  EF_SH4A = 0xc,
+  EF_SH2A = 0xd,
+  EF_SH4_NOFPU = 0x10,
+  EF_SH4A_NOFPU = 0x11,
+  EF_SH4_NOMMU_NOFPU = 0x12,
+  EF_SH2A_NOFPU = 0x13,
+  EF_SH3_NOMMU = 0x14,
+  EF_SH2A_SH4_NOFPU = 0x15,
+  EF_SH2A_SH3_NOFPU = 0x16,
+  EF_SH2A_SH4 = 0x17,
+  EF_SH2A_SH3E = 0x18,
+};
+
 // ELF Relocation types for S390/zSeries
 enum {
 #include "ELFRelocs/SystemZ.def"
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
index 20ea892292481..8328889f8afc0 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/CMakeLists.txt
@@ -10,6 +10,7 @@ add_llvm_component_library(LLVMSuperHDesc
   LINK_COMPONENTS
   MC
   SuperHInfo
+  SuperHCodeGen
   Support
   TargetParser
 
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
index e03896936980e..a6ff309001c7b 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.cpp
@@ -8,6 +8,8 @@
 
 #include "SuperHAsmBackend.h"
 #include "SuperHFixupKinds.h"
+#include "SuperHSubtarget.h"
+#include "TargetInfo/SuperHTargetInfo.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
@@ -22,6 +24,7 @@
 #include "llvm/MC/MCSection.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"
@@ -34,11 +37,14 @@
 
 using namespace llvm;
 
-SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI)
+#define DEBUG_TYPE "sh-asmbackend"
+
+SuperHAsmBackend::SuperHAsmBackend(const MCSubtargetInfo &STI, const MCInstrInfo *TII, 
+                                   uint8_t OSABI)
     : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
                        ? llvm::endianness::little
                        : llvm::endianness::big),
-      STI(STI), OSABI(OSABI) {}
+      STI(STI), TII(TII), OSABI(OSABI) {}
 
 bool SuperHAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
                                     const MCSubtargetInfo *STI) const {
@@ -140,6 +146,9 @@ bool SuperHAsmBackend::tryAddReloc(const MCFragment &F, const MCFixup &Fixup,
                                    bool IsResolved) {
   if (!IsResolved) {
     Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
+
+    MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
+    LLVM_DEBUG(dbgs() << "Recorded relocation " << Info.Name << "...\n");
     return false;
   }
   return true;
@@ -213,6 +222,11 @@ void SuperHAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
   Value = adjustFixupValue(*Asm, Fixup, Target, Value, IsResolved, Ctx,
                            getSubtargetInfo(F));
 
+  LLVM_DEBUG({
+    dbgs() << "Applying fixup " << Info.Name << " " << Value;
+    dbgs() << "...\n";
+  });
+
   if (!Value)
     return; // No encoding change.
 
@@ -241,5 +255,5 @@ MCAsmBackend *llvm::createSuperHAsmBackend(const Target &T,
                                            const MCTargetOptions &Options) {
   uint8_t OSABI =
       MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS());
-  return new SuperHAsmBackend(STI, OSABI);
+  return new SuperHAsmBackend(STI, T.createMCInstrInfo(), 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
index 27e4259347d81..272363af4c0c7 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHAsmBackend.h
@@ -23,10 +23,11 @@ class raw_ostream;
 class SuperHAsmBackend : public MCAsmBackend {
 protected:
   const MCSubtargetInfo &STI;
+  const MCInstrInfo *TII;
   uint8_t OSABI;
 
 public:
-  SuperHAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI);
+  SuperHAsmBackend(const MCSubtargetInfo &STI, const MCInstrInfo *TII, uint8_t OSABI);
   ~SuperHAsmBackend() override = default;
 
   std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
index 5c49947f963c3..12d3552b62a54 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHMCCodeEmitter.cpp
@@ -11,7 +11,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "SuperHFixupKinds.h"
+#include "SuperHInstrInfo.h"
 #include "SuperHMCTargetDesc.h"
+#include "SuperHSubtarget.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/bit.h"
@@ -44,9 +47,12 @@ namespace {
 
 class SuperHMCCodeEmitter : public MCCodeEmitter {
   MCContext &Ctx;
+  const SuperHInstrInfo *TII;
 
 public:
-  SuperHMCCodeEmitter(const MCInstrInfo &, MCContext &ctx) : Ctx(ctx) {}
+  SuperHMCCodeEmitter(const MCInstrInfo &II, MCContext &ctx) : 
+    Ctx(ctx),
+    TII((const SuperHInstrInfo *)&II) {}
   SuperHMCCodeEmitter(const SuperHMCCodeEmitter &) = delete;
   SuperHMCCodeEmitter &operator=(const SuperHMCCodeEmitter &) = delete;
   ~SuperHMCCodeEmitter() override = default;
@@ -74,6 +80,9 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                                   SmallVectorImpl<MCFixup> &Fixups,
                                   const MCSubtargetInfo &STI) const;
+  
+  MCFixup getFixupForOpcode(const MCInst &MI, const MCExpr *Expr,
+                                 MCContext &Ctx) const;
 
   // Displacement
   template <int Scale>
@@ -86,58 +95,22 @@ class SuperHMCCodeEmitter : public MCCodeEmitter {
   unsigned getPCRelOpValue(const MCInst &MI, unsigned OpNo,
                            SmallVectorImpl<MCFixup> &Fixups,
                            const MCSubtargetInfo &STI) const;
-
-  unsigned getOpBits(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups,
-                     const MCSubtargetInfo &STI) const;
 };
 
 } // end namespace
 
 #include "SuperHGenMCCodeEmitter.inc"
 
-// Some SuperH instructions are 32-bits wide.
-//
-// 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)
-    return true;
-
-  // Other SH2A 32-bit instructions
-  if ((Opcode & 0xF00F) == 0x3001)
-    return true;
-
-  // Opcodes bigger than 0xFFFF are always 32-bits.
-  return Opcode > 0xFFFF;
-}
-
-// Helper that gets the bits for the given instruction.
-unsigned SuperHMCCodeEmitter::getOpBits(const MCInst &MI,
-                                        SmallVectorImpl<MCFixup> &Fixups,
-                                        const MCSubtargetInfo &STI) const {
-  MCInst Inst = MCInst();
-  Inst.setOpcode(MI.getOpcode());
-  for (unsigned i = 0; i < MI.getNumOperands(); i++) {
-    Inst.addOperand(MCOperand::createImm(0));
-  }
-
-  return getBinaryCodeForInstr(Inst, Fixups, STI);
-}
-
 // @getFixupForOpcode - Helper that gets the neccesary fixup for
 // the given opcode.
 // This is neccesary due to the various opcodes that access memory
 // have different scaling factors applied.
-static MCFixup getFixupForOpcode(unsigned Opcode, const MCExpr *Expr,
-                                 MCContext &Ctx) {
-
-  // NOTE:  A few (DSP and SH2A) instructions are 32-bits wide.
-  //        We handle those quite crudely.
-  MCFixupKind Kind = isOpcode32(Opcode) ? FK_Data_4 : FK_Data_2;
+MCFixup SuperHMCCodeEmitter::getFixupForOpcode(const MCInst &MI, const MCExpr *Expr,
+                                               MCContext &Ctx) const {
+  int Size = TII->getInstSizeInBytes(MI);
+  MCFixupKind Kind = Size == 4 ? FK_Data_4 : FK_Data_2;
 
-  switch (Opcode) {
+  switch (MI.getOpcode()) {
   default:
     break;
 
@@ -190,22 +163,16 @@ void SuperHMCCodeEmitter::encodeInstruction(const MCInst &MI,
                                             SmallVectorImpl<char> &CB,
                                             SmallVectorImpl<MCFixup> &Fixups,
                                             const MCSubtargetInfo &STI) const {
+  auto Size = TII->getInstSizeInBytes(MI);
   uint64_t OpCode = getBinaryCodeForInstr(MI, Fixups, STI);
 
-  // NOTE:  All base instructions are 16-bit in SH ASM
-  //        But some instructions may be 32-bit for eg. SH2A or the DSP
-  //        extensions. This is ugly, but it'll work.
-  if (isOpcode32(OpCode)) {
-    support::endian::write(CB, (uint32_t)OpCode,
-                           Ctx.getAsmInfo().isLittleEndian()
-                               ? llvm::endianness::little
-                               : llvm::endianness::big);
-  } else {
-    support::endian::write(CB, (uint16_t)OpCode,
-                           Ctx.getAsmInfo().isLittleEndian()
-                               ? llvm::endianness::little
-                               : llvm::endianness::big);
+  // Fill buffer of data to insert to the instruction stream.
+  bool SwapValue = !Ctx.getAsmInfo().isLittleEndian();
+  for (unsigned i = 0; i < Size; ++i) {
+    unsigned Idx = SwapValue ? (Size - 1 - i) : i;
+    CB.push_back(uint8_t(((OpCode >> (Idx * 8)) & 0xff)));
   }
+
   ++MCNumEmitted;
 }
 
@@ -293,7 +260,7 @@ unsigned SuperHMCCodeEmitter::getExprOpValue(const MCInst &MI,
     return 0;
   }
   case MCExpr::ExprKind::SymbolRef: {
-    Fixups.push_back(getFixupForOpcode(MI.getOpcode(), Expr, Ctx));
+    Fixups.push_back(getFixupForOpcode(MI, Expr, Ctx));
     return 0;
   }
   case MCExpr::ExprKind::Constant: {
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
index 3e9aff7835a02..0823868e472f4 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.cpp
@@ -9,6 +9,7 @@
 #include "SuperHTargetStreamer.h"
 #include "SuperHInstPrinter.h"
 #include "SuperHMCTargetDesc.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/MCELFObjectWriter.h"
 #include "llvm/MC/MCRegister.h"
@@ -26,12 +27,31 @@ SuperHTargetAsmStreamer::SuperHTargetAsmStreamer(MCStreamer &S,
 
 SuperHTargetELFStreamer::SuperHTargetELFStreamer(MCStreamer &S,
                                                  const MCSubtargetInfo &STI)
-    : SuperHTargetStreamer(S) {
-  ELFObjectWriter &W = getStreamer().getWriter();
-  unsigned EFlags = W.getELFHeaderEFlags();
-  W.setELFHeaderEFlags(EFlags);
+    : SuperHTargetStreamer(S), W(getStreamer().getWriter()), STI(STI) {
+  setEFlags();      
 }
 
 MCELFStreamer &SuperHTargetELFStreamer::getStreamer() {
   return static_cast<MCELFStreamer &>(Streamer);
+}
+
+unsigned SuperHTargetELFStreamer::getCPUTypeFlag() const {
+  switch(STI.getTargetTriple().getSubArch()) {
+  default:                        return ELF::EF_SH_UNKNOWN;
+  case Triple::SuperHSubArch_1:   return ELF::EF_SH1;
+  case Triple::SuperHSubArch_2:   return ELF::EF_SH2;
+  case Triple::SuperHSubArch_2a:  return ELF::EF_SH2A;
+  case Triple::SuperHSubArch_2e:  return ELF::EF_SH2E;
+  case Triple::SuperHSubArch_3:   return ELF::EF_SH3;
+  case Triple::SuperHSubArch_3e:  return ELF::EF_SH3E;
+  case Triple::SuperHSubArch_4:   return ELF::EF_SH4;
+  case Triple::SuperHSubArch_4a:  return ELF::EF_SH4A;
+  }
+}
+
+void SuperHTargetELFStreamer::setEFlags() {
+  W.setELFHeaderEFlags(
+    W.getELFHeaderEFlags() | 
+    (getCPUTypeFlag() & ELF::EF_SH_MACH_MASK)
+  );
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.h b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.h
index 18b0819c744b7..202eaa31766da 100644
--- a/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.h
+++ b/llvm/lib/Target/SuperH/MCTargetDesc/SuperHTargetStreamer.h
@@ -30,9 +30,16 @@ class SuperHTargetAsmStreamer : public SuperHTargetStreamer {
 
 // This part is for ELF object output
 class SuperHTargetELFStreamer : public SuperHTargetStreamer {
+private:
+  ELFObjectWriter &W;
+  const MCSubtargetInfo &STI;
+
 public:
   SuperHTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
   MCELFStreamer &getStreamer();
+
+  void setEFlags();
+  unsigned getCPUTypeFlag() const;
 };
 } // end namespace llvm
 
diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index 5e47da6372fff..b3ce141fcee04 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -14,11 +14,13 @@
 
 #include "MCTargetDesc/SuperHMCTargetDesc.h"
 #include "SuperH.h"
+#include "SuperHConstantPoolValue.h"
 #include "SuperHInstrInfo.h"
 #include "SuperHMachineFunctionInfo.h"
 #include "SuperHSubtarget.h"
 #include "SuperHTargetMachine.h"
 
+#include "llvm/ADT/APInt.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -54,17 +56,21 @@ class SuperHExpandPseudo : public MachineFunctionPass {
   typedef MachineBasicBlock Block;
   typedef Block::iterator BlockIt;
 
+  const SuperHSubtarget *STI;
   const SuperHRegisterInfo *TRI;
   const TargetInstrInfo *TII;
 
   bool expandMBB(Block &MBB);
   bool expandMI(Block &MBB, BlockIt MBBI);
   template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
+  void getStackOffset(Block &MBB, BlockIt MBBI, Register FrameReg, 
+                      int64_t &Offset, uint8_t Bits, uint8_t Scale = 1);
 
   bool storeToFrame(Block &MBB, BlockIt MBBI, int Scale);
   bool storeToAddress(Block &MBB, BlockIt MBBI);
   bool loadFromFrame(Block &MBB, BlockIt MBBI, int Scale);
   bool loadFromAddress(Block &MBB, BlockIt MBBI);
+  bool loadFromImmediate(Block &MBB, BlockIt MBBI);
 };
 
 
@@ -74,19 +80,6 @@ class SuperHExpandPseudo : public MachineFunctionPass {
 //                                Helpers
 //===----------------------------------------------------------------------===//
 
-// getOffsetForStackOffset - Calculates how much to offset the stack pointer for
-// the indirect load/store to be in range.
-static int64_t getOffsetForStackOffset(const MachineFunction &MF, uint8_t Bits,
-                                       uint8_t Scale = 1) {
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
-
-  // The base value range for the instruction.
-  int64_t BM = ((1 << Bits) - 1) * Scale;
-  int64_t StackSize = MFI.getStackSize();
-  int64_t Slot = StackSize / BM;
-  return alignTo((BM * Slot) + (StackSize % BM), Scale);
-}
-
 // eraseMI - Helper that erases a machine instruction while respecting
 // the debug option to keep them.
 static bool eraseMI(MachineInstr &MI) {
@@ -100,11 +93,50 @@ static bool eraseMI(MachineInstr &MI) {
   return true;
 }
 
+// getStackOffset - Sets up the R1 stack reference register to access the 
+// stack at the given offset via negative add instructions, Offset is set
+// to the needed scaled offset for the stack access.
+void SuperHExpandPseudo::getStackOffset(Block &MBB, BlockIt MBBI, Register FrameReg, 
+                                        int64_t &Offset, uint8_t Bits, uint8_t Scale) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  const MachineFunction &MF = *MBB.getParent();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+
+  // Split the stack up into indexable chunks, each instruction has
+  // a fixed range that it can access, this range is positive only.
+  int64_t StackSize = MFI.getStackSize();
+  int64_t AccessRange = ((1 << Bits) * Scale);
+
+  // The stack grows down, so the offset needs to be adjusted so that
+  // we index correctly into the negative stack with a positive index.
+  int64_t RealOffset = (StackSize-Offset)-Scale;
+
+  // On big endian systems, adjust the pointer for
+  // < 32-bit offsets.
+  if (!STI->isLittleEndian() && Scale != 4)
+    RealOffset -= 4-(Scale-1);
+
+  int64_t SpAdjust = AccessRange * (alignTo(RealOffset, Scale) / AccessRange);
+
+  // Expand sequence to
+  // mov      <frame reg>,  r1
+  // add      #-SpOffset,   r1
+  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1).addReg(FrameReg);
+  if (SpAdjust != 0)
+    BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+        .addReg(SH::R1)
+        .addImm(-SpAdjust);
+
+  // Adjust the offset to be within the access range.
+  Offset = RealOffset % AccessRange;
+}
+
 
 
 
 //===----------------------------------------------------------------------===//
-//                              Frame Stores
+//                                Stores
 //===----------------------------------------------------------------------===//
 
 bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
@@ -112,19 +144,11 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
   const MachineFunction &MF = *MBB.getParent();
   MachineInstr &MI = *MBBI;
 
-  auto SrcReg = MI.getOperand(0).getReg();
   bool SrcIsKill = MI.getOperand(0).isKill();
+  auto SrcReg = MI.getOperand(0).getReg();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MF, 4, Scale);
-
-  // Expand sequence to
-  // mov      <frame reg>,  r1
-  // add      #-SpOffset,   r1
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1).addReg(FrameReg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-      .addReg(SH::R1)
-      .addImm(-SpOffset);
+  getStackOffset(MBB, MBBI, FrameReg, Offset, 4, Scale);
 
   switch (MI.getOpcode()) {
   default:
@@ -133,8 +157,9 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
 
     // mov      <src reg>,  r0
     // mov.b    r0, @(offset,r1)
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
-        .addReg(SrcReg, getKillRegState(SrcIsKill));
+    if (SrcReg != SH::R0)
+      BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
+          .addReg(SrcReg, getKillRegState(SrcIsKill));
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS4))
         .addReg(SH::R1, RegState::Kill)
         .addImm(Offset);
@@ -144,8 +169,9 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
 
     // mov      <src reg>,  r0
     // mov.w    r0, @(offset,r1)
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
-        .addReg(SrcReg, getKillRegState(SrcIsKill));
+    if (SrcReg != SH::R0)
+      BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R0)
+          .addReg(SrcReg, getKillRegState(SrcIsKill));
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS4))
         .addReg(SH::R1, RegState::Kill)
         .addImm(Offset);
@@ -153,7 +179,7 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
   }
   case SH::MOVLSF: {
 
-    // mov.b    <src reg>, @(offset,r1)
+    // mov.l    <src reg>, @(offset,r1)
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS4))
         .addReg(SrcReg, getKillRegState(SrcIsKill))
         .addReg(SH::R1, RegState::Kill)
@@ -171,6 +197,7 @@ bool SuperHExpandPseudo::storeToAddress(Block &MBB, BlockIt MBBI) {
   const MachineFunction &MF = *MBB.getParent();
   const SuperHMachineFunctionInfo *FI = MF.getInfo<SuperHMachineFunctionInfo>();
 
+  bool SrcIsKill = MI.getOperand(0).isKill();
   Register SrcReg = MI.getOperand(0).getReg();
   Register DstReg;
 
@@ -188,15 +215,21 @@ bool SuperHExpandPseudo::storeToAddress(Block &MBB, BlockIt MBBI) {
   default:
     llvm_unreachable("Expected valid MOV*SPtr opcode.");
   case SH::MOVBSP: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS)).addReg(SrcReg).addReg(DstReg);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS))
+      .addReg(SrcReg, getKillRegState(SrcIsKill))
+      .addReg(DstReg);
     break;
   }
   case SH::MOVWSP: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS)).addReg(SrcReg).addReg(DstReg);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS))
+      .addReg(SrcReg, getKillRegState(SrcIsKill))
+      .addReg(DstReg);
     break;
   }
   case SH::MOVLSP: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS)).addReg(SrcReg).addReg(DstReg);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS))
+      .addReg(SrcReg, getKillRegState(SrcIsKill))
+      .addReg(DstReg);
     break;
   }
   }
@@ -250,7 +283,7 @@ bool SuperHExpandPseudo::expand<SH::MOVLSP>(Block &MBB, BlockIt MBBI) {
 
 
 //===----------------------------------------------------------------------===//
-//                               Frame Loads
+//                               Loads
 //===----------------------------------------------------------------------===//
 
 bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
@@ -262,22 +295,14 @@ bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
   bool DstIsKill = MI.getOperand(0).isKill();
   auto FrameReg = MI.getOperand(1).getReg();
   auto Offset = MI.getOperand(2).getImm();
-  int64_t SpOffset = getOffsetForStackOffset(MF, 4, Scale);
-
-  // Expand sequence to
-  // mov      <frame reg>,  r1
-  // add      #-SpOffset,   r1
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1).addReg(FrameReg);
-  BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-      .addReg(SH::R1)
-      .addImm(-SpOffset);
+  getStackOffset(MBB, MBBI, FrameReg, Offset, 4, Scale);
 
   switch (MI.getOpcode()) {
   default:
     llvm_unreachable("Expected valid MOV*LPtr opcode.");
   case SH::MOVBLF: {
 
-    // mov.w    @(offset,r1), r0
+    // mov.b    @(offset,r1), r0
     // mov      r0,           <dst reg>
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL4))
         .addReg(SH::R1)
@@ -290,9 +315,11 @@ bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
   }
   case SH::MOVWLF: {
 
-    // mov.b    @(offset,r1), r0
+    // mov.w    @(offset,r1), r0
     // mov      r0,           <dst reg>
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4)).addReg(SH::R1).addImm(Offset);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL4))
+      .addReg(SH::R1)
+      .addImm(Offset);
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOV))
         .addReg(DstReg, getKillRegState(DstIsKill))
         .addReg(SH::R0, RegState::Define);
@@ -396,6 +423,44 @@ bool SuperHExpandPseudo::expand<SH::MOVLLP>(Block &MBB, BlockIt MBBI) {
 
 
 
+//===----------------------------------------------------------------------===//
+//                              Immediate Loads
+//===----------------------------------------------------------------------===//
+
+bool SuperHExpandPseudo::loadFromImmediate(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  auto DstReg = MI.getOperand(0).getReg();
+
+  if (MI.getOperand(1).isImm()) {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVI), DstReg)
+        .addImm(MI.getOperand(1).getImm());
+  } else if (MI.getOperand(1).isCPI()) {
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), DstReg)
+          .addConstantPoolIndex(MI.getOperand(1).getIndex());
+  }
+
+  return eraseMI(MI);
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVIB>(Block &MBB, BlockIt MBBI) {
+  return loadFromImmediate(MBB, MBBI);
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVIW>(Block &MBB, BlockIt MBBI) {
+  return loadFromImmediate(MBB, MBBI);
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVIL>(Block &MBB, BlockIt MBBI) {
+  return loadFromImmediate(MBB, MBBI);
+}
+
+
+
+
 //===----------------------------------------------------------------------===//
 //                              Bit Shifting
 //===----------------------------------------------------------------------===//
@@ -551,21 +616,6 @@ bool SuperHExpandPseudo::expand<SH::SRArr>(Block &MBB, BlockIt MBBI) {
 
 
 
-//===----------------------------------------------------------------------===//
-//                          Conditional Branching
-//===----------------------------------------------------------------------===//
-
-template <>
-bool SuperHExpandPseudo::expand<SH::BRCC>(Block &MBB, BlockIt MBBI) {
-  const DebugLoc &DL = MBBI->getDebugLoc();
-  MachineInstr &MI = *MBBI;
-
-  return eraseMI(MI);
-}
-
-
-
-
 //===----------------------------------------------------------------------===//
 //                            General Interface
 //===----------------------------------------------------------------------===//
@@ -592,9 +642,9 @@ bool SuperHExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
     return false;
 #endif
 
-  const SuperHSubtarget &STI = MF.getSubtarget<SuperHSubtarget>();
-  TRI = STI.getRegisterInfo();
-  TII = STI.getInstrInfo();
+  STI = &MF.getSubtarget<SuperHSubtarget>();
+  TRI = STI->getRegisterInfo();
+  TII = STI->getInstrInfo();
 
   for (Block &MBB : MF) {
     bool ContinueExpanding = true;
@@ -639,6 +689,9 @@ bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
     EXPAND(SH::MOVBLP);
     EXPAND(SH::MOVWLP);
     EXPAND(SH::MOVLLP);
+    EXPAND(SH::MOVIB);
+    EXPAND(SH::MOVIW);
+    EXPAND(SH::MOVIL);
     EXPAND(SH::SHLri);
     EXPAND(SH::SHRri);
     EXPAND(SH::SRAri);
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 4d899c91c3d8a..9d603b64a26eb 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -147,6 +147,7 @@ SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
   if (HasFP) {
 
     // Adjust down to remove FP.
+    FrameOffset += 4;
     FrameReg = RegInfo->getFrameRegister();
     return StackOffset::getFixed(-FrameOffset);
   }
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index f16b9ddf4d9f6..71b4ee5066c36 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -54,6 +54,7 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
 
   bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
   bool SelectFrAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
+  bool SelectImm(SDNode *Op, SDValue N, SDValue &Value);
 
   /// Return a target constant with the specified value of type i4.
   inline SDValue getI4Imm(int64_t Imm, const SDLoc &DL) {
@@ -119,38 +120,32 @@ bool SuperHDAGToDAGISel::SelectInlineAsmMemoryOperand(
 bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
                                     SDValue &Disp) {
   auto DL = CurDAG->getDataLayout();
-  MVT PtrVT = getTargetLowering()->getPointerTy(DL);
 
-  // if the address is a wrapper, get the underlying data.
-  if (N.getOpcode() == SHISD::WRAPPER) {
+  MachineFunction &MF = CurDAG->getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+
+  switch(N.getOpcode()) {
+  case SHISD::WRAPPER:
+  case ISD::LOAD:
+    // Address is a wrapper, get the underlying data.
     Base = N;
-    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32);
+    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
     return true;
+  default:
+    break;
   }
 
-  // Constant displacements has more operands, if there's 2 or more, assume
-  // the address may be a form of displacement.
-  if (N.getNumOperands() >= 2) { 
-    if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
-
-      // Handle frame index + offset
-      if (N.getOperand(0).getOpcode() == ISD::FrameIndex) {
-        int RHSC = (int)RHS->getZExtValue();
-        int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
-
-        Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
-        Disp = CurDAG->getTargetConstant(RHSC, SDLoc(Op), MVT::i32);
-        return true;
-      }
-
-      // Handle reg + offset
-      if (N.getOpcode() == ISD::ADD) {
-        Base = N.getOperand(0);
-        Disp =
-            CurDAG->getTargetConstant(RHS->getZExtValue(), SDLoc(Op), MVT::i32);
-        return true;
-      }
+  // Address is a constant pointer, lower to constpool.
+  MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
+  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
+    if (auto *CPV = SFI->tryGetConstant(C, *CurDAG, SHCP::no_modifier)) {
+      SDValue TGA = CurDAG->getTargetConstantPool(CPV, VT, Align(4), 0);
+      MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVLI, SDLoc(Op), MVT::i32, TGA);
+      Base = SDValue(Res, 0);
+      Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
+      return true;
     }
+
   }
   return false;
 }
@@ -164,10 +159,33 @@ bool SuperHDAGToDAGISel::SelectFrAddr(SDNode *Op, SDValue N, SDValue &Base,
   // if the address is a frame index get the TargetFrameIndex.
   if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
-    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32);
+    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
     return true;
   }
+  return false;
+}
+
+// Selects frame address operands.
+bool SuperHDAGToDAGISel::SelectImm(SDNode *Op, SDValue N, SDValue &Value) {
+  auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
+  auto DL = SDLoc(N);
 
+  MachineFunction &MF = CurDAG->getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+
+  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
+
+    // Constant would fit in immediate
+    if (isInt<8>(C->getSExtValue())) {
+      Value = CurDAG->getTargetConstant(*C->getConstantIntValue(), DL, C->getValueType(0));
+      return true;
+    }
+
+    if (auto *CPV = SFI->tryGetConstant(C, *CurDAG, SHCP::no_modifier)) {
+      Value = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+      return true;
+    }
+  }
   return false;
 }
 
@@ -250,14 +268,6 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
   default:
     break;
   case SHCC::COND_EQ: {
-
-    // TST would be faster in this case.
-    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
-      if (C->getSExtValue() == 0) {
-        Res = CurDAG->getMachineNode(SH::TST, DL, MVT::Glue, LHS, LHS);
-        break;
-      }
-    }
     Res = CurDAG->getMachineNode(SH::CMPEQ, DL, MVT::Glue, LHS, RHS);
     break;
   }
@@ -285,6 +295,10 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
     Res = CurDAG->getMachineNode(SH::CMPPZ, DL, MVT::Glue, LHS, RHS);
     break;
   }
+  case SHCC::COND_Z: {
+    Res = CurDAG->getMachineNode(SH::TST, DL, MVT::Glue, LHS, LHS);
+    break;
+  }
   }
 
   if (Res) {
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 8c6e40b2cb945..e6cd552d855dd 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -82,11 +82,6 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::MUL, VT, Custom);
   }
 
-  // Constants have special lowering rules depending on their length.
-  for (MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64}) {
-    setOperationAction(ISD::Constant, VT, Custom);
-  }
-
   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
   setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
@@ -158,11 +153,25 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
   default:
     break;
   case ISD::SETEQ: {
+    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
+      if (C->getSExtValue() == 0) {
+        SHcc = SHCC::COND_Z;
+        SHocc = SHCC::COND_T;
+        break;
+      }
+    }
     SHcc = SHCC::COND_EQ;
     SHocc = SHCC::COND_T;
     break;
   }
   case ISD::SETNE: {
+    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
+      if (C->getSExtValue() == 0) {
+        SHcc = SHCC::COND_Z;
+        SHocc = SHCC::COND_F;
+        break;
+      }
+    }
     SHcc = SHCC::COND_EQ;
     SHocc = SHCC::COND_F;
     break;
@@ -171,14 +180,14 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
     // Swap operands and reverse the branching condition.
     std::swap(LHS, RHS);
     SHcc = SHCC::COND_GE;
-    SHocc = SHCC::COND_T;
+    SHocc = SHCC::COND_F;
     break;
   }
   case ISD::SETLE: {
     // Swap operands and reverse the branching condition.
     std::swap(LHS, RHS);
     SHcc = SHCC::COND_GT;
-    SHocc = SHCC::COND_T;
+    SHocc = SHCC::COND_F;
     break;
   }
   case ISD::SETGT: {
@@ -219,18 +228,22 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
     // Swap operands and reverse the branching condition.
     std::swap(LHS, RHS);
     SHcc = SHCC::COND_HS;
-    SHocc = SHCC::COND_T;
+    SHocc = SHCC::COND_F;
     break;
   }
   case ISD::SETULE: {
     // Swap operands and reverse the branching condition.
     std::swap(LHS, RHS);
     SHcc = SHCC::COND_HI;
-    SHocc = SHCC::COND_T;
+    SHocc = SHCC::COND_F;
     break;
   }
   }
 
+  LLVM_DEBUG(dbgs() << "Lowered CC " << CC << " to " 
+                    << getCondName(SHcc) << ":"
+                    << getCondName(SHocc) << " ...\n");
+
   InCC = DAG.getTargetConstant(SHcc, DL, MVT::i8);
   OutCC = DAG.getTargetConstant(SHocc, DL, MVT::i8);
   return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, InCC);
@@ -325,12 +338,11 @@ SDValue SuperHTargetLowering::LowerConstant(SDValue Op,
 
     // Constant would fit in immediate
     if (isInt<8>(C->getSExtValue())) {
-      return Op;
+      return DAG.getTargetConstant(*C->getConstantIntValue(), DL, C->getValueType(0));
     }
 
     // Constant would NOT fit in immediate, lower to constpool.
-    SDValue Const =
-        DAG.getSignedTargetConstant(C->getSExtValue(), DL, C->getValueType(0));
+    SDValue Const = DAG.getTargetConstant(*C->getConstantIntValue(), DL, C->getValueType(0));
     return DAG.getNode(SHISD::WRAPPER, DL, C->getValueType(0), Const);
   }
   return SDValue();
@@ -515,7 +527,7 @@ SuperHTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                   bool IsVarArg,
                                   const SmallVectorImpl<ISD::OutputArg> &Outs,
                                   const SmallVectorImpl<SDValue> &OutVals,
-                                  const SDLoc &dl, SelectionDAG &DAG) const {
+                                  const SDLoc &DL, SelectionDAG &DAG) const {
 
   SmallVector<CCValAssign, 16> RVLocs;
   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
@@ -525,13 +537,35 @@ SuperHTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
   MachineFunction &MF = DAG.getMachineFunction();
   CCInfo.AnalyzeReturn(Outs, RetCC_SH);
 
-  // Fill out values into registers.
+  // Set up return values.
   SDValue Glue;
-  SmallVector<SDValue, 4> RetOps(1, Chain);
+  SmallVector<SDValue, 5> RetOps;
+  RetOps.push_back(Chain);
+
+  // Copy the result values into the output registers.
   for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
     CCValAssign &VA = RVLocs[i];
+    SDValue OutVal = OutVals[i];
 
-    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
+    // Promote values to the appropriate types.
+    switch(VA.getLocInfo()) {
+    case CCValAssign::SExt:
+      OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal);
+      break;
+    case CCValAssign::ZExt:
+      OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal);
+      break;
+    case CCValAssign::AExt:
+      OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal);
+      break;
+    case CCValAssign::BCvt:
+      OutVal = DAG.getBitcast(VA.getLocVT(), OutVal);
+      break;
+    default:
+      break;
+    }
+
+    Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Glue);
     Glue = Chain.getValue(1);
     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
   }
@@ -543,17 +577,12 @@ SuperHTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 
   // Update chain.
   RetOps[0] = Chain;
+
+  // Add the glue if we have it.
   if (Glue.getNode())
     RetOps.push_back(Glue);
 
-  return DAG.getNode(SHISD::RET_GLUE, dl, MVT::Other, RetOps);
-}
-
-SDValue
-SuperHTargetLowering::getPICJumpTableRelocBase(SDValue Table,
-                                               SelectionDAG &DAG) const {
-  return DAG.getRegister(Subtarget->getRegisterInfo()->getGOTRegister(),
-                         getPointerTy(DAG.getDataLayout()));
+  return DAG.getNode(SHISD::RET_GLUE, DL, MVT::Other, RetOps);
 }
 
 
@@ -564,6 +593,13 @@ SuperHTargetLowering::getPICJumpTableRelocBase(SDValue Table,
 //                              CALL LOWERING
 //===----------------------------------------------------------------------===//
 
+SDValue
+SuperHTargetLowering::getPICJumpTableRelocBase(SDValue Table,
+                                               SelectionDAG &DAG) const {
+  return DAG.getRegister(Subtarget->getRegisterInfo()->getGOTRegister(),
+                         getPointerTy(DAG.getDataLayout()));
+}
+
 SDValue
 SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI,
                                 SmallVectorImpl<SDValue> &InVals) const {
@@ -715,16 +751,16 @@ SuperHTargetLowering::LowerCall(CallLoweringInfo &CLI,
   assert(Mask && "Missing call preserved mask for calling convention");
   Ops.push_back(DAG.getRegisterMask(Mask));
 
-  if (InGlue.getNode()) {
+  if (InGlue.getNode())
     Ops.push_back(InGlue);
-  }
 
   Chain = DAG.getNode(SHISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
   InGlue = Chain.getValue(1);
 
   // Create the CALLSEQ_END node.
   Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
-  InGlue = Chain.getValue(1);
+  if (!Ins.empty())
+    InGlue = Chain.getValue(1);
 
   return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
                          InVals);
@@ -744,27 +780,13 @@ SDValue SuperHTargetLowering::LowerCallResult(
   CCInfo.AnalyzeCallResult(Ins, RetCC_SH);
 
   // Copy all of the result registers out of their specified physreg.
-  for (CCValAssign const &VA : RVLocs) {
-    SDValue RV;
-    RV = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), InGlue);
-    Chain = RV.getValue(1);
+  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
+    CCValAssign &VA = RVLocs[i];
+    Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), InGlue)
+      .getValue(1);
+    SDValue RV = Chain.getValue(0);
     InGlue = Chain.getValue(2);
 
-    // The callee promoted the return value, so insert an Assert?ext SDNode so
-    // we won't promote the value again in this function.
-    switch (VA.getLocInfo()) {
-    case CCValAssign::SExt:
-      RV = DAG.getNode(ISD::AssertSext, dl, VA.getLocVT(), RV,
-                       DAG.getValueType(VA.getValVT()));
-      break;
-    case CCValAssign::ZExt:
-      RV = DAG.getNode(ISD::AssertZext, dl, VA.getLocVT(), RV,
-                       DAG.getValueType(VA.getValVT()));
-      break;
-    default:
-      break;
-    }
-
     // Truncate the register down to the return value type.
     if (VA.isExtInLoc())
       RV = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RV);
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 2ba57525a55fd..91f3fe7ca2c43 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -20,6 +20,7 @@
 #include "SuperHTargetMachine.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -117,6 +118,36 @@ unsigned SuperHInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
     const MCInstrDesc &Desc = get(Opcode);
     return Desc.getSize();
   }
+  case SH::CONSTPOOL_ENTRY:
+    // If this machine instr is a constant pool entry, 
+    // its size is recorded as operand #2.
+    return MI.getOperand(2).getImm();
+  case TargetOpcode::EH_LABEL:
+  case TargetOpcode::IMPLICIT_DEF:
+  case TargetOpcode::KILL:
+  case TargetOpcode::DBG_VALUE:
+    return 0;
+  case TargetOpcode::INLINEASM:
+  case TargetOpcode::INLINEASM_BR: {
+    // TODO: Add inline ASM support.
+    return 0;
+  }
+  }
+}
+
+unsigned SuperHInstrInfo::getInstSizeInBytes(const MCInst &MI) const {
+  unsigned Opcode = MI.getOpcode();
+
+  switch (Opcode) {
+  // A regular instruction
+  default: {
+    const MCInstrDesc &Desc = get(Opcode);
+    return Desc.getSize();
+  }
+  case SH::CONSTPOOL_ENTRY:
+    // If this machine instr is a constant pool entry, 
+    // its size is recorded as operand #2.
+    return MI.getOperand(2).getImm();
   case TargetOpcode::EH_LABEL:
   case TargetOpcode::IMPLICIT_DEF:
   case TargetOpcode::KILL:
@@ -178,7 +209,6 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 
 Register SuperHInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
                                              int &FrameIndex) const {
-  dbgs() << "isStoreToStackSlot\n";
   if (MI.getOperand(0).isReg() && MI.getOperand(1).isFI() &&
       MI.getOperand(2).getImm() == 0) {
     FrameIndex = MI.getOperand(1).getIndex();
@@ -222,7 +252,6 @@ void SuperHInstrInfo::storeRegToStackSlot(
 
 Register SuperHInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
                                               int &FrameIndex) const {
-  dbgs() << "isLoadFromStackSlot\n";
   if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
       MI.getOperand(1).getImm() == 0) {
     FrameIndex = MI.getOperand(0).getIndex();
@@ -278,89 +307,111 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
                                     MachineBasicBlock *&FBB,
                                     SmallVectorImpl<MachineOperand> &Cond,
                                     bool AllowModify) const {
-  // Start from the bottom of the block and work up, examining the
-  // terminator instructions.
-  MachineBasicBlock::iterator I = MBB.end();
-  MachineBasicBlock::iterator UnCondBrIter = MBB.end();
+  auto UncondBranch =
+      std::pair<MachineBasicBlock::reverse_iterator, MachineBasicBlock *>{
+          MBB.rend(), nullptr};
+
+  // Erase any instructions if allowed at the end of the scope.
+  std::vector<std::reference_wrapper<llvm::MachineInstr>> EraseList;
+  llvm::scope_exit FinalizeOnReturn([&EraseList] {
+    for (auto &Ref : EraseList)
+      Ref.get().eraseFromParent();
+  });
+
+  for (auto I = MBB.rbegin(); I != MBB.rend(); I = std::next(I)) {
+    unsigned Opcode = I->getOpcode();
+    if (I->isDebugInstr()) 
+      continue;
 
-  while (I != MBB.begin()) {
-    --I;
-    if (I->isDebugInstr()) {
+    // Skip NOPs
+    if (Opcode == SH::NOP)
       continue;
-    }
 
     // Working from the bottom, when we see a non-terminator
     // instruction, we're done.
-    if (!isUnpredicatedTerminator(*I)) {
+    if (!isUnpredicatedTerminator(*I))
       break;
-    }
 
     // A terminator that isn't a branch can't easily be handled
     // by this analysis.
-    if (!I->getDesc().isBranch()) {
+    if (!I->isBranch())
       return true;
-    }
 
     // Handle unconditional branches.
-    if (I->getOpcode() == SH::BRA) {
-      UnCondBrIter = I;
+    if (Opcode == SH::BRA) {
+      if (!I->getOperand(0).isMBB())
+        return true;
+
+      UncondBranch = {I, I->getOperand(0).getMBB()};
+
+      // TBB is used to indicate the unconditional destination.
+      TBB = UncondBranch.second;
 
-      if (!AllowModify) {
-        TBB = I->getOperand(0).getMBB();
+      if (!AllowModify)
         continue;
-      }
 
-      // If the block has any instructions after a BRA, delete them.
-      MBB.erase(std::next(I), MBB.end());
+      // If the block has any instructions after a JMP, erase them.
+      EraseList.insert(EraseList.begin(), MBB.rbegin(), I);
       Cond.clear();
       FBB = nullptr;
 
       // Delete the BRA if it's equivalent to a fall-through.
       if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
         TBB = nullptr;
-        I->eraseFromParent();
-        I = MBB.end();
-        UnCondBrIter = MBB.end();
+        EraseList.push_back(*I);
+        UncondBranch = {MBB.rend(), nullptr};
         continue;
       }
-
-      // TBB is used to indicate the unconditinal destination.
-      TBB = I->getOperand(0).getMBB();
       continue;
     }
 
     // Handle conditional branches.
-    SHCC::CondCode BranchCode = getCondFromBranchOp(I->getOpcode());
-    if (BranchCode == SHCC::COND_INVALID) {
-      return true; // Can't handle indirect branch.
-    }
+    SHCC::CondCode BranchCode = getCondFromBranchOp(Opcode);
+
+    // Can't handle indirect branch.
+    if (BranchCode == SHCC::COND_INVALID)
+      return true; 
+
+    if (I->getOperand(1).isUndef())
+      return true;
 
     // Working from the bottom, handle the first conditional branch.
     if (Cond.empty()) {
-      MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
-      if (AllowModify && UnCondBrIter != MBB.end() &&
-          MBB.isLayoutSuccessor(TargetBB)) {
+      if (!I->getOperand(0).isMBB())
+        return true;
 
-        BranchCode = getOppositeCondCode(BranchCode);
-        auto JNCC = getBrCond(BranchCode, false);
+      MachineBasicBlock *CondBranchTarget = I->getOperand(0).getMBB();
+      if (UncondBranch.first != MBB.rend()) {
+        assert(std::next(UncondBranch.first) == I && "Wrong block layout.");
 
-        MachineBasicBlock::iterator OldInst = I;
-        BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), JNCC)
-            .addMBB(UnCondBrIter->getOperand(0).getMBB());
-        BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SH::BRA))
-            .addMBB(TargetBB);
+        if (AllowModify && MBB.isLayoutSuccessor(CondBranchTarget)) {
 
-        OldInst->eraseFromParent();
-        UnCondBrIter->eraseFromParent();
+          BranchCode = getOppositeCondCode(BranchCode);
+          auto BNCC = getBrCond(BranchCode, false);
 
-        // Restart the analysis.
-        UnCondBrIter = MBB.end();
-        I = MBB.end();
+          BuildMI(MBB, *UncondBranch.first, MBB.rfindDebugLoc(I), BNCC)
+              .addMBB(UncondBranch.second);
+
+          EraseList.push_back(*I);
+          EraseList.push_back(*UncondBranch.first);
+
+          TBB = UncondBranch.second;
+          FBB = nullptr;
+          Cond.push_back(MachineOperand::CreateImm(BranchCode));
+        } else {
+
+          // Otherwise preserve TBB, FBB and Cond as requested
+          TBB = CondBranchTarget;
+          FBB = UncondBranch.second;
+          Cond.push_back(MachineOperand::CreateImm(BranchCode));
+        }
+
+        UncondBranch = {MBB.rend(), nullptr};
         continue;
       }
 
-      FBB = TBB;
-      TBB = I->getOperand(0).getMBB();
+      TBB = CondBranchTarget;
+      FBB = nullptr;
       Cond.push_back(MachineOperand::CreateImm(BranchCode));
       continue;
     }
@@ -370,18 +421,15 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
     assert(Cond.size() == 1);
     assert(TBB);
 
-    // Only handle the case where all conditional branches branch to
-    // the same destination.
-    if (TBB != I->getOperand(0).getMBB()) {
-      return true;
-    }
-
-    SHCC::CondCode OldBranchCode = (SHCC::CondCode)Cond[0].getImm();
     // If the conditions are the same, we can leave them alone.
-    if (OldBranchCode == BranchCode) {
+    SHCC::CondCode OldBranchCode = static_cast<SHCC::CondCode>(Cond[0].getImm());
+    if (!I->getOperand(0).isMBB())
+      return true;
+    auto *NewTBB = I->getOperand(0).getMBB();
+    if (OldBranchCode == BranchCode && TBB == NewTBB)
       continue;
-    }
 
+    // If they differ we cannot do much here.
     return true;
   }
 
@@ -411,6 +459,7 @@ unsigned SuperHInstrInfo::insertBranch(
   unsigned Count = 0;
   SHCC::CondCode CC = (SHCC::CondCode)Cond[0].getImm();
   auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC, false)).addMBB(TBB);
+  LLVM_DEBUG(dbgs() << "Created cc branch for " << getCondName(CC) << "...\n");
 
   if (BytesAdded)
     *BytesAdded += getInstSizeInBytes(CondMI);
@@ -437,14 +486,13 @@ unsigned SuperHInstrInfo::removeBranch(MachineBasicBlock &MBB,
 
   while (I != MBB.begin()) {
     --I;
-    if (I->isDebugInstr()) {
+    if (I->isDebugValue())
       continue;
-    }
 
-    if (I->getOpcode() != SH::BRA &&
-        getCondFromBranchOp(I->getOpcode()) == ISD::SETCC_INVALID) {
+    unsigned Opcode = I->getOpcode();
+    if (Opcode != SH::BRA && Opcode != SH::NOP &&
+        getCondFromBranchOp(Opcode) == SHCC::COND_INVALID)
       break;
-    }
 
     // Remove the branch.
     if (BytesRemoved)
@@ -461,6 +509,7 @@ bool SuperHInstrInfo::reverseBranchCondition(
     SmallVectorImpl<MachineOperand> &Cond) const {
   assert(Cond.size() == 1 && "Invalid SH branch condition!");
 
+  LLVM_DEBUG(dbgs() << "Reversed branch condition...\n");
   SHCC::CondCode CC = (SHCC::CondCode)Cond[0].getImm();
   Cond[0].setImm(getOppositeCondCode(CC));
   return false;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index b74c2b286cc90..9b6cb9a2ea49c 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -39,11 +39,29 @@ enum CondCode {
   COND_HS, //!< Higher than or same
   COND_PL, //!< Greater than 0
   COND_PZ, //!< Greater than or equal to 0
+  COND_Z,  //!< Zero
   COND_T,  //!< True
   COND_F,  //!< False
   COND_INVALID
 };
 
+static StringRef getCondName(CondCode CC) {
+  switch(CC) {
+  default:
+    return "<invalid>";
+  case COND_EQ: return "eq";
+  case COND_GT: return "gt";
+  case COND_GE: return "ge";
+  case COND_HI: return "hi";
+  case COND_HS: return "hs";
+  case COND_PL: return "pl";
+  case COND_PZ: return "pz";
+  case COND_Z:  return "z";
+  case COND_T:  return "t";
+  case COND_F:  return "f";
+  }
+}
+
 } // end of namespace SHCC
 
 class SuperHInstrInfo : public SuperHGenInstrInfo {
@@ -71,6 +89,7 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
 
   // Instruction Info
   unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
+  unsigned getInstSizeInBytes(const MCInst &MI) const;
 
   /// Return the noop instruction to use for a noop.
   MCInst getNop() const override;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 9014ed43ad4a6..09deeb844da75 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -141,18 +141,18 @@ class SHScaledOp<ValueType vt, string name, int scale, bit encode = 1>
 // Immediate
 class SHImmOp<int width, ValueType vt>
       : Operand<vt>, ImmLeaf<vt, [{ return isInt<}] # width # [{>(Imm); }]> {
-    let ParserMatchClass = SHImmClass<width>;
-    let OperandType = "OPERAND_IMMEDIATE";
-    let PrintMethod = "printImm";
-    let MCOperandPredicate = [{
-      int64_t Imm;
-      if (MCOp.evaluateAsConstantImm(Imm))
-        return isInt<}] # width # [{>(Imm)
-      return false;
-    }];
+  let ParserMatchClass = SHImmClass<width>;
+  let OperandType = "OPERAND_IMMEDIATE";
+  let PrintMethod = "printImm";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (MCOp.evaluateAsConstantImm(Imm))
+      return isInt<}] # width # [{>(Imm)
+    return false;
+  }];
 }
 
-def imm8 : SHImmOp<8, i32>;
+def imm8  : SHImmOp<8, i32>;
 
 // Displacement
 class SHDispOp<int width, ValueType vt, int scale = 0>
@@ -231,14 +231,19 @@ def IGPR    : SHIndirectRegOp<GPR, "">;
 def IGPRInc : SHIndirectRegOp<GPR, "Inc">;
 def IGPRDec : SHIndirectRegOp<GPR, "Dec">;
 
+let WantsRoot = true in {
+
 // Addressing mode pattern reg+disp
-let WantsRoot = true in
 def addr : ComplexPattern<iPTR, 2, "SelectAddr">;
 
 // Addressing mode pattern reg+disp (Frame)
-let WantsRoot = true in
 def fraddr : ComplexPattern<iPTR, 2, "SelectFrAddr">;
 
+// Immediate lowering.
+def anyimm8 : ComplexPattern<i8, 1, "SelectImm", [imm]>;
+def anyimm16 : ComplexPattern<i16, 1, "SelectImm", [imm]>;
+def anyimm32 : ComplexPattern<i32, 1, "SelectImm", [imm]>;
+}
 
 
 
@@ -322,7 +327,7 @@ let hasSideEffects = 0 in
 def MOVI          : InstRnI8<0b1110000000000000,
                             (outs GPR:$Rn), (ins imm8:$imm),
                             "mov $imm,$Rn",
-                            [(set i32:$Rn, imm:$imm)]>;
+                            []>;
 
 // mova @(disp, PC), R0
 let hasSideEffects = 0, mayLoad = 1, Uses = [PC], Defs = [R0], isDelayIllegal = 1 in
@@ -1450,7 +1455,7 @@ def Select32    : SHSelectPseudo<(outs GPR:$dst),
                                  (SHselectcc i32:$src, i32:$src2, timm:$cc))]>;
 
 //===--------------------------------------------------------------------------===//
-// Frame Load/Store
+// Load/Store
 //===--------------------------------------------------------------------------===//
 
 let mayLoad = 1, isReMaterializable = 1 in {
@@ -1488,13 +1493,13 @@ def MOVLLF    : SHLoadPseudo<(outs GPR:$Rn), (ins (memri $Rm, $disp):$src),
                             []>;
 }
 
-let mayStore = 1, isReMaterializable = 1 in {
+let isReMaterializable = 1 in {
 
 // STORE TO ADDRESS
 let Defs = [R0, R1] in
 def MOVBSP    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                              "! MOVBSP $src, $dst",
-                             []>;
+                             [(truncstorei8 i32:$src, addr:$dst)]>;
 
 let Defs = [R0, R1] in
 def MOVWSP    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
@@ -1510,20 +1515,37 @@ def MOVLSP    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
 let Defs = [R0, R1] in
 def MOVBSF    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                              "! MOVBSF $src, $dst",
-                             []>;
+                             [(truncstorei8 i32:$src, fraddr:$dst)]>;
 
 let Defs = [R0, R1] in
 def MOVWSF    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                              "! MOVWSF $src, $dst",
-                             []>;
+                             [(truncstorei16 i32:$src, fraddr:$dst)]>;
 
 let Defs = [R1] in
 def MOVLSF    : SHStorePseudo<(outs), (ins GPR:$src, (memri $Rm, $disp):$dst),
                              "! MOVLSF $src, $dst",
-                             []>;
+                             [(store i32:$src, fraddr:$dst)]>;
 
 }
 
+//===--------------------------------------------------------------------------===//
+// Load Immediate
+//===--------------------------------------------------------------------------===//
+
+let isReMaterializable = 1 in {
+def MOVIB         : SHPseudo<(outs GPR:$dst), (ins i8imm:$src),
+                             "! MOVIB $src, $dst",
+                             [(set i8:$dst, anyimm8:$src)]>;
+
+def MOVIW         : SHPseudo<(outs GPR:$dst), (ins i16imm:$src),
+                             "! MOVIW $src, $dst",
+                             [(set i16:$dst, anyimm16:$src)]>;
+
+def MOVIL         : SHPseudo<(outs GPR:$dst), (ins i32imm:$src),
+                             "! MOVIL $src, $dst",
+                             [(set i32:$dst, anyimm32:$src)]>;
+}
 
 
 
@@ -1636,15 +1658,4 @@ def : Pat<(i32 (sextloadi8     i32:$src)), (EXTSB (EXTUB (MOVBL     i32:$src)))>
 def : Pat<(i32 (sextloadi16    i32:$src)),        (EXTSW (MOVWL     i32:$src))>;
 def : Pat<(i32 (zextloadi1     i32:$src)),        (EXTUB (MOVBL     i32:$src))>;
 def : Pat<(i32 (zextloadi8     i32:$src)),        (EXTUB (MOVBL     i32:$src))>;
-def : Pat<(i32 (zextloadi16    i32:$src)),        (EXTUW (MOVWL     i32:$src))>;
-
-//===--------------------------------------------------------------------------===//
-// Stores
-//===--------------------------------------------------------------------------===//
-def : Pat<(store          i32:$src,    i32:$dst),      (MOVLS   i32:$src,    i32:$dst)>;
-def : Pat<(truncstorei8   i32:$src,   addr:$dst),      (MOVBSP  i32:$src,   addr:$dst)>;
-def : Pat<(truncstorei16  i32:$src,   addr:$dst),      (MOVWSP  i32:$src,   addr:$dst)>;
-def : Pat<(store          i32:$src,   addr:$dst),      (MOVLSP  i32:$src,   addr:$dst)>;
-def : Pat<(truncstorei8   i32:$src, fraddr:$dst),      (MOVBSF  i32:$src, fraddr:$dst)>;
-def : Pat<(truncstorei16  i32:$src, fraddr:$dst),      (MOVWSF  i32:$src, fraddr:$dst)>;
-def : Pat<(store          i32:$src, fraddr:$dst),      (MOVLSF  i32:$src, fraddr:$dst)>;
\ No newline at end of file
+def : Pat<(i32 (zextloadi16    i32:$src)),        (EXTUW (MOVWL     i32:$src))>;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index 50e43d82f9729..34dd819c77129 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -45,9 +45,7 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
                            unsigned FIOperandNum,
                            RegScavenger *RS = nullptr) const override;
 
-  bool requiresRegisterScavenging(const MachineFunction &MF) const override {
-    return true;
-  }
+  bool requiresRegisterScavenging(const MachineFunction &MF) const override { return true; }
 
   // Helpers
   Register getFrameRegister() const;
diff --git a/llvm/lib/TargetParser/SuperHTargetParser.cpp b/llvm/lib/TargetParser/SuperHTargetParser.cpp
index 07560907f9ac5..34baf5a6c57bd 100644
--- a/llvm/lib/TargetParser/SuperHTargetParser.cpp
+++ b/llvm/lib/TargetParser/SuperHTargetParser.cpp
@@ -48,7 +48,7 @@ static SuperH::ISAKind consumeISAKind(StringRef &ArchName) {
     
     // Enforce eb suffix for sh2e and sh3e.
     if (KV.Name.ends_with("e")) {
-      if (!ArchName.ends_with("eb") && !ArchName.ends_with("el"))
+      if (!ArchName.ends_with("eeb") && !ArchName.ends_with("eel"))
         continue;
     }
 

>From d19264fe7ce3414622e456ce3986e7c8cec932e8 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 27 Sep 2026 03:30:00 +0200
Subject: [PATCH 60/67] Implement division in compiler-rt

---
 compiler-rt/lib/builtins/superh/divhi3.S  | 26 +++++++++++++++++++++-
 compiler-rt/lib/builtins/superh/divqi3.S  | 27 ++++++++++++++++++++++-
 compiler-rt/lib/builtins/superh/divsi3.S  | 25 +++++++++++++++++++--
 compiler-rt/lib/builtins/superh/udivhi3.S | 21 +++++++++++++++++-
 compiler-rt/lib/builtins/superh/udivqi3.S | 21 +++++++++++++++++-
 compiler-rt/lib/builtins/superh/udivsi3.S | 22 ++++++++++++++++--
 6 files changed, 134 insertions(+), 8 deletions(-)

diff --git a/compiler-rt/lib/builtins/superh/divhi3.S b/compiler-rt/lib/builtins/superh/divhi3.S
index 4e63a33a1d715..796ad35eb16ad 100644
--- a/compiler-rt/lib/builtins/superh/divhi3.S
+++ b/compiler-rt/lib/builtins/superh/divhi3.S
@@ -20,5 +20,29 @@
 
 
 FUNCTION_BEGIN __sh_divhi3
-	
+	shll16	r5
+	exts.w  r4, r4
+	tst 	r5, r5
+	bt 		.Ldbz
+	mov 	r4, r3
+	rotcl 	r3
+	subc 	r1, r1
+	mov 	#0, r3
+	subc 	r3, r4
+	div0s 	r5, r1
+	.rept 16
+	rotcl   r4        
+	div1    r5,r1
+	.endr
+	rotcl   r4
+	addc    r3, r4
+	exts.w  r4, r0
+	mov 	#0, r1
+	rts
+	nop
+.Ldbz:
+	mov 	#0, r0
+	mov 	r0, r1
+	rts
+	nop
 FUNCTION_END __sh_divhi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/divqi3.S b/compiler-rt/lib/builtins/superh/divqi3.S
index cb73cadb22103..173d910018ae6 100644
--- a/compiler-rt/lib/builtins/superh/divqi3.S
+++ b/compiler-rt/lib/builtins/superh/divqi3.S
@@ -20,5 +20,30 @@
 
 
 FUNCTION_BEGIN __sh_divqi3
-	
+	shll16	r5
+	shll8	r5
+	exts.b  r4, r4
+	tst 	r5, r5
+	bt 		.Ldbz
+	mov 	r4, r3
+	rotcl 	r3
+	subc 	r1, r1
+	mov 	#0, r3
+	subc 	r3, r4
+	div0s 	r5, r1
+	.rept 8
+	rotcl   r4        
+	div1    r5,r1
+	.endr
+	rotcl   r4
+	addc    r3, r4
+	exts.b  r4, r0
+	mov 	#0, r1
+	rts
+	nop
+.Ldbz:
+	mov 	#0, r0
+	mov 	r0, r1
+	rts
+	nop
 FUNCTION_END __sh_divqi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/divsi3.S b/compiler-rt/lib/builtins/superh/divsi3.S
index 07da658506941..211fc9649a6d5 100644
--- a/compiler-rt/lib/builtins/superh/divsi3.S
+++ b/compiler-rt/lib/builtins/superh/divsi3.S
@@ -13,12 +13,33 @@
 	.type \name, @function
 \name:
 	.endm
-
 	.macro FUNCTION_END name
 	.size  \name, . - \name
 	.endm
 
 
 FUNCTION_BEGIN __sh_divsi3
-	
+	tst 	r5,r5
+	bt 		.Ldbz
+	mov 	r4, r3
+	rotcl 	r3
+	subc 	r1, r1
+	mov 	#0, r3
+	subc 	r3, r4
+	div0s 	r5, r1
+	.rept 32
+	rotcl   r4        
+	div1    r5,r1
+	.endr
+	rotcl   r4
+	addc    r3, r4
+	mov 	r2, r0
+	mov 	#0, r1
+	rts
+	nop
+.Ldbz:
+	mov 	#0, r0
+	mov 	r0, r1
+	rts
+	nop
 FUNCTION_END __sh_divsi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivhi3.S b/compiler-rt/lib/builtins/superh/udivhi3.S
index 4eda163340250..b35bee0fdf2ff 100644
--- a/compiler-rt/lib/builtins/superh/udivhi3.S
+++ b/compiler-rt/lib/builtins/superh/udivhi3.S
@@ -20,5 +20,24 @@
 
 
 FUNCTION_BEGIN __sh_udivhi3
-	
+	extu.w 	r4, r4
+	extu.w  r5, r5
+	tst 	r5, r5
+	bt 		.Ldbz
+	cmp/hs  r4, r5
+	bt      .Ldbz
+	div0u
+	.rept 16
+	div1 	r5, r4
+	.endr
+	rotcl 	r5
+	extu.w  r5, r0
+	mov 	#0, r1
+	rts
+	nop
+.Ldbz:
+	mov 	#0, r0
+	mov 	r0, r1
+	rts
+	nop
 FUNCTION_END __sh_udivhi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivqi3.S b/compiler-rt/lib/builtins/superh/udivqi3.S
index 1c03576115a40..c0de79a794673 100644
--- a/compiler-rt/lib/builtins/superh/udivqi3.S
+++ b/compiler-rt/lib/builtins/superh/udivqi3.S
@@ -20,5 +20,24 @@
 
 
 FUNCTION_BEGIN __sh_udivqi3
-	
+	extu.b 	r4, r4
+	extu.b  r5, r5
+	tst 	r5, r5
+	bt 		.Ldbz
+	cmp/hs  r4, r5
+	bt      .Ldbz
+	div0u
+	.rept 8
+	div1 	r5, r4
+	.endr
+	rotcl 	r4
+	extu.w  r4, r0
+	mov 	#0, r1
+	rts
+	nop
+.Ldbz:
+	mov 	#0, r0
+	mov 	r0, r1
+	rts
+	nop
 FUNCTION_END __sh_udivqi3
\ No newline at end of file
diff --git a/compiler-rt/lib/builtins/superh/udivsi3.S b/compiler-rt/lib/builtins/superh/udivsi3.S
index 22386367f52ba..6ce810d42d468 100644
--- a/compiler-rt/lib/builtins/superh/udivsi3.S
+++ b/compiler-rt/lib/builtins/superh/udivsi3.S
@@ -13,12 +13,30 @@
 	.type \name, @function
 \name:
 	.endm
-
 	.macro FUNCTION_END name
 	.size  \name, . - \name
 	.endm
 
 
 FUNCTION_BEGIN __sh_udivsi3
-	
+	tst 	r5, r5
+	bt 		.Ldbz
+	cmp/hs  r4, r5
+	bt      .Ldbz
+	mov 	#0, r1
+	div0u
+	.rept 32
+	rotcl	r4
+	div1 	r5, r1
+	.endr
+	rotcl 	r5
+	mov 	r5, r0
+	mov 	#0, r1
+	rts
+	nop
+.Ldbz:
+	mov 	#0, r0
+	mov 	r0, r1
+	rts
+	nop
 FUNCTION_END __sh_udivsi3
\ No newline at end of file

>From 9e6871227247070d23edcf23d1b4394d97821ee0 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 27 Sep 2026 03:56:25 +0200
Subject: [PATCH 61/67] Fix divsi3 return sequence

---
 compiler-rt/lib/builtins/superh/divsi3.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/lib/builtins/superh/divsi3.S b/compiler-rt/lib/builtins/superh/divsi3.S
index 211fc9649a6d5..4e89b74397525 100644
--- a/compiler-rt/lib/builtins/superh/divsi3.S
+++ b/compiler-rt/lib/builtins/superh/divsi3.S
@@ -33,7 +33,7 @@ FUNCTION_BEGIN __sh_divsi3
 	.endr
 	rotcl   r4
 	addc    r3, r4
-	mov 	r2, r0
+	mov 	r4, r0
 	mov 	#0, r1
 	rts
 	nop

>From 266a4da928d9fa9c37988e483d51811bb7d127ef Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Sun, 27 Sep 2026 07:22:11 +0200
Subject: [PATCH 62/67] Add stack parameters and returns

---
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 72 ++++++++++++++-----
 .../lib/Target/SuperH/SuperHFrameLowering.cpp |  6 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 48 ++++++++++++-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  9 +--
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp | 44 +++++++++---
 5 files changed, 144 insertions(+), 35 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index b3ce141fcee04..8b7c463a5ed41 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -110,7 +110,7 @@ void SuperHExpandPseudo::getStackOffset(Block &MBB, BlockIt MBBI, Register Frame
 
   // The stack grows down, so the offset needs to be adjusted so that
   // we index correctly into the negative stack with a positive index.
-  int64_t RealOffset = (StackSize-Offset)-Scale;
+  int64_t RealOffset = (StackSize-Offset);
 
   // On big endian systems, adjust the pointer for
   // < 32-bit offsets.
@@ -209,31 +209,49 @@ bool SuperHExpandPseudo::storeToAddress(Block &MBB, BlockIt MBBI) {
     }
   } else if (MI.getOperand(1).isReg()) {
     DstReg = MI.getOperand(1).getReg();
-  }
+  }  
+
+  auto Offset = MI.getOperand(2).getImm();
+  unsigned Opc;
 
   switch (MI.getOpcode()) {
   default:
     llvm_unreachable("Expected valid MOV*SPtr opcode.");
   case SH::MOVBSP: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBS))
-      .addReg(SrcReg, getKillRegState(SrcIsKill))
-      .addReg(DstReg);
+    if (Offset == 0)
+      Opc = SH::MOVBS;
+    else
+      Opc = SH::MOVBS4;
     break;
   }
   case SH::MOVWSP: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWS))
-      .addReg(SrcReg, getKillRegState(SrcIsKill))
-      .addReg(DstReg);
+    if (Offset == 0)
+      Opc = SH::MOVWS;
+    else
+      Opc = SH::MOVWS4;
     break;
   }
   case SH::MOVLSP: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLS))
-      .addReg(SrcReg, getKillRegState(SrcIsKill))
-      .addReg(DstReg);
+    if (Offset == 0)
+      Opc = SH::MOVLS;
+    else
+      Opc = SH::MOVLS4;
     break;
   }
   }
 
+  // TODO: Allow bigger accesses.
+  if (Offset == 0) {
+    BuildMI(MBB, MBBI, DL, TII->get(Opc))
+      .addReg(SrcReg, getKillRegState(SrcIsKill))
+      .addReg(DstReg);
+  } else {
+    BuildMI(MBB, MBBI, DL, TII->get(Opc))
+      .addReg(SrcReg, getKillRegState(SrcIsKill))
+      .addReg(DstReg)
+      .addImm(Offset);
+  }
+
   return eraseMI(MI);
 }
 
@@ -358,23 +376,47 @@ bool SuperHExpandPseudo::loadFromAddress(Block &MBB, BlockIt MBBI) {
     SrcReg = MI.getOperand(1).getReg();
   }
 
+  auto Offset = MI.getOperand(2).getImm();
+  unsigned Opc;
+
   switch (MI.getOpcode()) {
   default:
     llvm_unreachable("Expected valid MOV*LPtr opcode.");
   case SH::MOVBLP: {
+    if (Offset == 0)
+      Opc = SH::MOVBL;
+    else
+      Opc = SH::MOVBL4;
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVBL), DstReg).addReg(SrcReg);
     break;
   }
   case SH::MOVWLP: {
+    if (Offset == 0)
+      Opc = SH::MOVWL;
+    else
+      Opc = SH::MOVWL4;
     BuildMI(MBB, MBBI, DL, TII->get(SH::MOVWL), DstReg).addReg(SrcReg);
     break;
   }
   case SH::MOVLLP: {
-    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLL), DstReg).addReg(SrcReg);
+    if (Offset == 0)
+      Opc = SH::MOVLL;
+    else
+      Opc = SH::MOVLL4;
     break;
   }
   }
 
+  // TODO: Allow bigger accesses.
+  if (Offset == 0) {
+    BuildMI(MBB, MBBI, DL, TII->get(Opc), DstReg)
+      .addReg(SrcReg);
+  } else {
+    BuildMI(MBB, MBBI, DL, TII->get(Opc), DstReg)
+      .addReg(SrcReg)
+      .addImm(Offset);
+  }
+
   return eraseMI(MI);
 }
 
@@ -469,8 +511,6 @@ template <>
 bool SuperHExpandPseudo::expand<SH::SHLri>(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   auto DstReg = MI.getOperand(0).getReg();
   auto SrcReg = MI.getOperand(1).getReg();
@@ -511,8 +551,6 @@ template <>
 bool SuperHExpandPseudo::expand<SH::SHRri>(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   auto DstReg = MI.getOperand(0).getReg();
   auto SrcReg = MI.getOperand(1).getReg();
@@ -553,8 +591,6 @@ template <>
 bool SuperHExpandPseudo::expand<SH::SRAri>(Block &MBB, BlockIt MBBI) {
   const DebugLoc &DL = MBBI->getDebugLoc();
   MachineInstr &MI = *MBBI;
-  const MachineFunction &MF = *MBB.getParent();
-  const MachineFrameInfo &MFI = MF.getFrameInfo();
 
   auto DstReg = MI.getOperand(0).getReg();
   auto SrcReg = MI.getOperand(1).getReg();
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 9d603b64a26eb..53e2e5eb733f5 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -147,14 +147,14 @@ SuperHFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
   if (HasFP) {
 
     // Adjust down to remove FP.
-    FrameOffset += 4;
+    FrameOffset -= 4;
     FrameReg = RegInfo->getFrameRegister();
-    return StackOffset::getFixed(-FrameOffset);
+    return StackOffset::getFixed(FrameOffset);
   }
 
   // R15 base
   FrameReg = RegInfo->getStackRegister(); // r15
-  return StackOffset::getFixed(-FrameOffset);
+  return StackOffset::getFixed(FrameOffset);
 }
 
 
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 71b4ee5066c36..1a296ac707ab5 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -124,9 +124,10 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
   MachineFunction &MF = CurDAG->getMachineFunction();
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
 
+
   switch(N.getOpcode()) {
   case SHISD::WRAPPER:
-  case ISD::LOAD:
+
     // Address is a wrapper, get the underlying data.
     Base = N;
     Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
@@ -135,6 +136,30 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
     break;
   }
 
+  // Handle address + offset
+  if (N.getOpcode() == ISD::ADD) {
+    auto LHS = N.getOperand(0);
+    auto RHS = N.getOperand(1);
+
+    // Frame should not lower to Addr
+    if (isa<FrameIndexSDNode>(LHS))
+      return false;
+
+    if (isa<ConstantSDNode>(RHS)) {
+      auto *C = dyn_cast<ConstantSDNode>(RHS);
+      Base = LHS;
+      Disp = CurDAG->getTargetConstant(*C->getConstantIntValue(), SDLoc(Op), C->getValueType(0));
+      return true;
+    }
+  }
+
+  // Handle indirect address.
+  if (N.getOpcode() == ISD::CopyFromReg) {
+    Base = N;
+    Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
+    return true;
+  }
+
   // Address is a constant pointer, lower to constpool.
   MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
   if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
@@ -145,7 +170,6 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
       Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
       return true;
     }
-
   }
   return false;
 }
@@ -162,6 +186,26 @@ bool SuperHDAGToDAGISel::SelectFrAddr(SDNode *Op, SDValue N, SDValue &Base,
     Disp = CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i8);
     return true;
   }
+
+  // Handle frame indexing with offset.
+  if (N.getOpcode() == ISD::ADD) {
+    auto LHS = N.getOperand(0);
+    auto RHS = N.getOperand(1);
+    if (isa<FrameIndexSDNode>(LHS) && isa<ConstantSDNode>(RHS)) {
+      auto *F = dyn_cast<FrameIndexSDNode>(LHS);
+      auto *C = dyn_cast<ConstantSDNode>(RHS);
+      Base = CurDAG->getTargetFrameIndex(F->getIndex(), PtrVT);
+      Disp = CurDAG->getTargetConstant(*C->getConstantIntValue(), SDLoc(Op), C->getValueType(0));
+      return true;
+    }
+
+    if (isa<RegisterSDNode>(LHS) && isa<ConstantSDNode>(RHS)) {
+      auto *C = dyn_cast<ConstantSDNode>(RHS);
+      Base = LHS;
+      Disp = CurDAG->getTargetConstant(*C->getConstantIntValue(), SDLoc(Op), C->getValueType(0));
+      return true;
+    }
+  }
   return false;
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index 09deeb844da75..af19392ef8467 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -1438,19 +1438,19 @@ def BRCC       : SHPseudo<(outs), (ins brtarget:$disp, i8imm:$cc),
 
 def Select8     : SHSelectPseudo<(outs GPR:$dst),
                                 (ins GPR:$src, GPR:$src2, i8imm:$cc),
-                                "; Select8 PSEUDO",
+                                "! Select8 PSEUDO",
                                 [(set i8:$dst,
                                  (SHselectcc i8:$src, i8:$src2, timm:$cc))]>;
 
 def Select16    : SHSelectPseudo<(outs GPR:$dst),
                                 (ins GPR:$src, GPR:$src2, i8imm:$cc),
-                                "; Select16 PSEUDO",
+                                "! Select16 PSEUDO",
                                 [(set i16:$dst,
                                  (SHselectcc i16:$src, i16:$src2, timm:$cc))]>;
 
 def Select32    : SHSelectPseudo<(outs GPR:$dst),
                                 (ins GPR:$src, GPR:$src2, i8imm:$cc),
-                                "; Select32 PSEUDO",
+                                "! Select32 PSEUDO",
                                 [(set i32:$dst,
                                  (SHselectcc i32:$src, i32:$src2, timm:$cc))]>;
 
@@ -1591,7 +1591,8 @@ def SRArr       : SHPseudo<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2),
 // 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)>;
+def SHFrmIdx : SHPseudo<(outs GPR:$dst), (ins GPR:$src, disp12:$src2),
+                        "! frame index">;
 
 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in
 /// the function.  The first operand is the ID# for this instruction, the second
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 470e1e6dfda9a..27dcc6380fc56 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -110,7 +110,7 @@ static void replaceFI(const MachineFunction &MF, MachineBasicBlock::iterator II,
                       unsigned FIOperandNum, int Offset, Register FramePtr) {
 
   MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
-  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
+  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(-Offset);
 }
 
 bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
@@ -126,17 +126,45 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
       TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
   const TargetInstrInfo &TII =
       *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
-  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
 
-  // Get the register offset to fetch.
+  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
+  int64_t FrameOffset = MI.getOperand(FIOperandNum+1).getImm();
   Register FrameReg;
-  int64_t Offset =
-      TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
+
+  int64_t Offset = 
+      TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed() + 
+      FrameOffset;
+
+  // Load effective address of stack slot.
+  if (MI.getOpcode() == SH::SHFrmIdx) {
+    Register DstReg = MI.getOperand(0).getReg();
+    if (DstReg != FrameReg) {
+      TII.copyPhysReg(MBB, MI, DL, DstReg, FrameReg, false, false, false);
+    }
+
+    if (Offset > 0) {
+
+      // Skip over the SHFrmIdx instruction.
+      II++;
+
+      while(Offset != 0) {
+        int64_t NextOff = Offset % 255;
+
+        // Add offset to register.
+        BuildMI(MBB, II, DL, TII.get(SH::ADDI), DstReg)
+            .addReg(DstReg, RegState::Kill)
+            .addImm(NextOff);
+
+        Offset -= NextOff;
+      }
+    }
+
+    MI.eraseFromParent();
+    return true;
+  }
 
   LLVM_DEBUG({
-    int64_t Fo =
-        TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
-    dbgs() << "Eliminiate FI " << FrameIndex << " @ SP[" << -Fo << "]...\n";
+    dbgs() << "Eliminiate FI " << FrameIndex << " @ SP[" << -Offset << "]...\n";
   });
 
   replaceFI(MF, II, MI, DL, FIOperandNum, Offset, FrameReg);

>From dcf9f475c2816c028b9b1338b0b802f13e8d28d9 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Mon, 28 Sep 2026 01:27:23 +0200
Subject: [PATCH 63/67] Work around crash from branch folding

---
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 11 +++++++----
 llvm/lib/Target/SuperH/SuperHInstrInfo.td  |  8 ++++----
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 91f3fe7ca2c43..19e302968d398 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -372,7 +372,7 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
     if (BranchCode == SHCC::COND_INVALID)
       return true; 
 
-    if (I->getOperand(1).isUndef())
+    if (I->getNumOperands() >= 2 && I->getOperand(1).isUndef())
       return true;
 
     // Working from the bottom, handle the first conditional branch.
@@ -449,7 +449,8 @@ unsigned SuperHInstrInfo::insertBranch(
 
   if (Cond.empty()) {
     assert(!FBB && "Unconditional branch with multiple successors!");
-    auto &MI = *BuildMI(&MBB, DL, get(SH::BRA)).addMBB(TBB);
+    auto &MI = *BuildMI(&MBB, DL, get(SH::BRA))
+      .addMBB(TBB);
     if (BytesAdded)
       *BytesAdded += getInstSizeInBytes(MI);
     return 1;
@@ -458,7 +459,8 @@ unsigned SuperHInstrInfo::insertBranch(
   // Conditional branch.
   unsigned Count = 0;
   SHCC::CondCode CC = (SHCC::CondCode)Cond[0].getImm();
-  auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC, false)).addMBB(TBB);
+  auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC, false))
+    .addMBB(TBB);
   LLVM_DEBUG(dbgs() << "Created cc branch for " << getCondName(CC) << "...\n");
 
   if (BytesAdded)
@@ -467,7 +469,8 @@ unsigned SuperHInstrInfo::insertBranch(
 
   if (FBB) {
     // Two-way Conditional branch. Insert the second branch.
-    auto &MI = *BuildMI(&MBB, DL, get(SH::BRA)).addMBB(FBB);
+    auto &MI = *BuildMI(&MBB, DL, get(SH::BRA))
+      .addMBB(FBB);
     if (BytesAdded)
       *BytesAdded += getInstSizeInBytes(MI);
     ++Count;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.td b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
index af19392ef8467..d83a1e8add66a 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -1101,25 +1101,25 @@ let hasSideEffects = 0, Constraints = "$src = $Rn" in {
 //===--------------------------------------------------------------------------===//
 
 let isTerminator = 1 in {
-  let isBranch = 1, Uses = [SR] in
+  let isBranch = 1 in
   def BF              : InstD8<0b1000101100000000, 
                               (outs), (ins brtarget:$disp),
                               "bf $disp",
                               []>;
 
-  let isBranch = 1, hasDelaySlot = 1, Uses = [SR] in
+  let isBranch = 1, hasDelaySlot = 1 in
   def BFS             : InstD8<0b1000111100000000, 
                               (outs), (ins brtarget:$disp),
                               "bf/s $disp",
                               []>;
 
-  let isBranch = 1, Uses = [SR] in
+  let isBranch = 1 in
   def BT              : InstD8<0b1000100100000000, 
                               (outs), (ins brtarget:$disp),
                               "bt $disp",
                               []>;
 
-  let isBranch = 1, hasDelaySlot = 1, Uses = [SR] in
+  let isBranch = 1, hasDelaySlot = 1 in
   def BTS             : InstD8<0b1000110100000000, 
                               (outs), (ins brtarget:$disp),
                               "bt/s $disp",

>From 29a21dc6c3c3f54dfcb41e9d9fea0f887edf0b76 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 29 Sep 2026 00:36:06 +0200
Subject: [PATCH 64/67] Update against upstream

---
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp  | 8 --------
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp  | 5 -----
 llvm/lib/Target/SuperH/SuperHRegisterInfo.h    | 2 --
 llvm/lib/Target/SuperH/SuperHTargetMachine.cpp | 2 +-
 llvm/lib/Target/SuperH/SuperHTargetMachine.h   | 4 ++--
 5 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index e6cd552d855dd..552dcb7019710 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -177,15 +177,11 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
     break;
   }
   case ISD::SETLT: {
-    // Swap operands and reverse the branching condition.
-    std::swap(LHS, RHS);
     SHcc = SHCC::COND_GE;
     SHocc = SHCC::COND_F;
     break;
   }
   case ISD::SETLE: {
-    // Swap operands and reverse the branching condition.
-    std::swap(LHS, RHS);
     SHcc = SHCC::COND_GT;
     SHocc = SHCC::COND_F;
     break;
@@ -225,15 +221,11 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
     break;
   }
   case ISD::SETULT: {
-    // Swap operands and reverse the branching condition.
-    std::swap(LHS, RHS);
     SHcc = SHCC::COND_HS;
     SHocc = SHCC::COND_F;
     break;
   }
   case ISD::SETULE: {
-    // Swap operands and reverse the branching condition.
-    std::swap(LHS, RHS);
     SHcc = SHCC::COND_HI;
     SHocc = SHCC::COND_F;
     break;
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 27dcc6380fc56..5cc5a7a1709a9 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -41,11 +41,6 @@ SuperHRegisterInfo::SuperHRegisterInfo(const SuperHSubtarget &ST)
                             /*PC*/ SH::PC),
       Subtarget(ST) {}
 
-const TargetRegisterClass *
-SuperHRegisterInfo::getPointerRegClass(unsigned Kind) const {
-  return &SH::GPRRegClass;
-}
-
 const MCPhysReg *
 SuperHRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
   return CSR_SH_SaveList;
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index 34dd819c77129..9c42adf3298f5 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -33,8 +33,6 @@ class SuperHRegisterInfo : public SuperHGenRegisterInfo {
   const uint32_t *getCallPreservedMask(const MachineFunction &MF,
                                        CallingConv::ID CC) const override;
   const uint32_t *getNoPreservedMask() const override;
-  const TargetRegisterClass *
-  getPointerRegClass(unsigned Kind = 0) const override;
   BitVector getReservedRegs(const MachineFunction &MF) const override;
   const TargetRegisterClass *
   getLargestLegalSuperClass(const TargetRegisterClass *RC,
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index ef89a5ea017a2..75542e5efdbb2 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -91,7 +91,7 @@ SuperHTargetMachine::SuperHTargetMachine(const Target &T, const Triple &TT,
                                          std::optional<Reloc::Model> RM,
                                          std::optional<CodeModel::Model> CM,
                                          CodeGenOptLevel OL, bool JIT)
-    : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,
+    : CodeGenTargetMachineImpl(T, TT, CPU, FS, Options,
                                RM.value_or(Reloc::Static),
                                getEffectiveCodeModel(CM, CodeModel::Small), OL),
       TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.h b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
index 5fab6d45aa076..49706933ab773 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.h
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
@@ -29,8 +29,8 @@ class SuperHTargetMachine : public CodeGenTargetMachineImpl {
   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);
+                      std::optional<CodeModel::Model> CM, 
+                      CodeGenOptLevel OL, bool JIT);
   ~SuperHTargetMachine() override;
 
   MachineFunctionInfo *

>From 0f40b836a3b690b09d19c01fc85b4d08d5ba1342 Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 29 Sep 2026 00:42:11 +0200
Subject: [PATCH 65/67] Temporarily disable branch folding

---
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 19e302968d398..1bbc822a33d46 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -307,6 +307,7 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
                                     MachineBasicBlock *&FBB,
                                     SmallVectorImpl<MachineOperand> &Cond,
                                     bool AllowModify) const {
+#ifdef SH_ENABLE_BRANCH_FOLDING
   auto UncondBranch =
       std::pair<MachineBasicBlock::reverse_iterator, MachineBasicBlock *>{
           MBB.rend(), nullptr};
@@ -434,6 +435,9 @@ bool SuperHInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
   }
 
   return false;
+#else
+  return true;
+#endif
 }
 
 unsigned SuperHInstrInfo::insertBranch(

>From 0797fedb129de64eab4c038427f7ce0ae55ffeef Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 29 Sep 2026 00:54:20 +0200
Subject: [PATCH 66/67] Fix cc branch operand order

---
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp |  3 +++
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 10 +++++++++-
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |  2 +-
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 1a296ac707ab5..23f8068b24cfc 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -305,6 +305,9 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
                           ->getZExtValue();
   SDLoc DL(N);
 
+  // Comparison order is reverse in SuperH
+  std::swap(LHS, RHS);
+
   // NOTE:  The comparisons just set the T bit, it's up to later instructions
   //        to interpret the T bit as positive or negative.
   SDNode *Res = nullptr;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 552dcb7019710..28a51c1a08364 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -142,7 +142,7 @@ static bool RetCC_SH_SRet(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 //===----------------------------------------------------------------------===//
 //                        CONDITIONAL BRANCH LOWERING
 //===----------------------------------------------------------------------===//
-SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
+SDValue SuperHTargetLowering::getSHCmp(SDValue &LHS, SDValue &RHS,
                                        ISD::CondCode CC, SDValue &OutCC,
                                        SelectionDAG &DAG, SDLoc DL) const {
   SDValue InCC;
@@ -177,11 +177,15 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
     break;
   }
   case ISD::SETLT: {
+    // Swap operands and reverse the branching condition.
+    std::swap(LHS, RHS);
     SHcc = SHCC::COND_GE;
     SHocc = SHCC::COND_F;
     break;
   }
   case ISD::SETLE: {
+    // Swap operands and reverse the branching condition.
+    std::swap(LHS, RHS);
     SHcc = SHCC::COND_GT;
     SHocc = SHCC::COND_F;
     break;
@@ -221,11 +225,15 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue LHS, SDValue RHS,
     break;
   }
   case ISD::SETULT: {
+    // Swap operands and reverse the branching condition.
+    std::swap(LHS, RHS);
     SHcc = SHCC::COND_HS;
     SHocc = SHCC::COND_F;
     break;
   }
   case ISD::SETULE: {
+    // Swap operands and reverse the branching condition.
+    std::swap(LHS, RHS);
     SHcc = SHCC::COND_HI;
     SHocc = SHCC::COND_F;
     break;
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 0b484c9323250..77100366b8f41 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -78,7 +78,7 @@ class SuperHTargetLowering : public TargetLowering {
   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
-  SDValue getSHCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &OutCC,
+  SDValue getSHCmp(SDValue &LHS, SDValue &RHS, ISD::CondCode CC, SDValue &OutCC,
                    SelectionDAG &DAG, SDLoc DL) const;
 
   // Inserters

>From 6e3a2e76fb7ac9becc24614dcb4d12732be1fc9d Mon Sep 17 00:00:00 2001
From: LunaTheFoxgirl <luna at foxgirls.gay>
Date: Tue, 29 Sep 2026 09:26:57 +0200
Subject: [PATCH 67/67] Preliminary FPU support

---
 llvm/lib/Target/SuperH/SuperH.td              |  18 +
 llvm/lib/Target/SuperH/SuperHCallingConv.td   |  18 +
 .../Target/SuperH/SuperHExpandPseudoInsts.cpp | 180 +++++++-
 .../lib/Target/SuperH/SuperHFrameLowering.cpp |   3 +-
 llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp | 102 +++--
 llvm/lib/Target/SuperH/SuperHISelLowering.cpp | 281 ++++++++-----
 llvm/lib/Target/SuperH/SuperHISelLowering.h   |   5 +-
 llvm/lib/Target/SuperH/SuperHInstrFPU.td      | 394 ++++++++++++++++++
 llvm/lib/Target/SuperH/SuperHInstrFormats.td  |  36 ++
 llvm/lib/Target/SuperH/SuperHInstrInfo.cpp    |  94 +++--
 llvm/lib/Target/SuperH/SuperHInstrInfo.h      |   4 +-
 llvm/lib/Target/SuperH/SuperHInstrInfo.td     |  42 +-
 .../SuperH/SuperHMachineFunctionInfo.cpp      |  29 ++
 .../Target/SuperH/SuperHMachineFunctionInfo.h |   3 +
 llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp |  36 +-
 llvm/lib/Target/SuperH/SuperHRegisterInfo.h   |   7 +-
 llvm/lib/Target/SuperH/SuperHSubtarget.cpp    |  22 +-
 llvm/lib/Target/SuperH/SuperHSubtarget.h      |   3 +-
 .../lib/Target/SuperH/SuperHTargetMachine.cpp |  45 +-
 llvm/lib/Target/SuperH/SuperHTargetMachine.h  |   5 +-
 20 files changed, 1063 insertions(+), 264 deletions(-)
 create mode 100644 llvm/lib/Target/SuperH/SuperHInstrFPU.td

diff --git a/llvm/lib/Target/SuperH/SuperH.td b/llvm/lib/Target/SuperH/SuperH.td
index 91da9eda8d02a..0bd40f64fb503 100644
--- a/llvm/lib/Target/SuperH/SuperH.td
+++ b/llvm/lib/Target/SuperH/SuperH.td
@@ -70,6 +70,24 @@ def FeatureSH4A     : SubtargetFeature<"sh4a", "SHArchVersion", "SH4A",
                           "SH-4A ISA Support",
                           [FeatureSH4, FeatureFSCA, FeatureFSRRA]>;
 
+//===--------------------------------------------------------------------------===//
+// Predicates
+//===--------------------------------------------------------------------------===//
+
+def HasFSCA     : Predicate<"Subtarget->hasFSCA()">;
+def HasFSRRA    : Predicate<"Subtarget->hasFSRRA()">;
+def HasFPU      : Predicate<"Subtarget->hasFPU()">;
+def HasDSP      : Predicate<"Subtarget->hasDSP()">;
+def HasSH2      : Predicate<"Subtarget->hasSH2Inst()">;
+def HasSH2E     : Predicate<"Subtarget->hasSH2EInst()">;
+def HasSH2A     : Predicate<"Subtarget->hasSH2AInst()">;
+def HasSH3      : Predicate<"Subtarget->hasSH3Inst()">;
+def HasSH3E     : Predicate<"Subtarget->hasSH3EInst()">;
+def HasSH4      : Predicate<"Subtarget->hasSH4Inst()">;
+def HasSH4A     : Predicate<"Subtarget->hasSH4AInst()">;
+def HasF64      : Predicate<"Subtarget->hasFP64()">,
+                  AssemblerPredicate<(all_of FeatureFPU)>;
+
 //===----------------------------------------------------------------------===//
 // SuperH Processors
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHCallingConv.td b/llvm/lib/Target/SuperH/SuperHCallingConv.td
index 937eca18d3001..f65257f574cbe 100644
--- a/llvm/lib/Target/SuperH/SuperHCallingConv.td
+++ b/llvm/lib/Target/SuperH/SuperHCallingConv.td
@@ -12,12 +12,24 @@
 // SuperH CDECL Calling Convention
 //===-------------------------------------------------------------------------===//
 
+/// CCIfSubtarget - Match if the current subtarget has a feature F.
+class CCIfSubtarget<string F, CCAction A, string Invert = "">
+    : CCIf<!strconcat(Invert,
+                      "State.getMachineFunction().getSubtarget<SuperHSubtarget>().",
+                      F),
+           A>;
+
 def CC_SH : CallingConv<[
 
   // All lower size parameters are promoted to 32-bit
   CCIfType<[i1, i8, i16],  CCPromoteToType<i32>>,
   CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7]>>,
 
+  // 32-bit floats
+  CCIfSubtarget<"hasFPU()", 
+      CCIfType<[f32], CCAssignToReg<[FR4,  FR5,  FR6,  FR7,  FR8,  FR9,
+                                     FR10, FR11]>>>,
+
   CCAssignToStack<4, 4>
 ]>;
 
@@ -28,6 +40,12 @@ def RetCC_SH : CallingConv<[
   CCIfType<[i1, i8, i16],  CCPromoteToType<i32>>,
   CCIfType<[i32],  CCAssignToReg<[R0, R1, R2, R3]>>,
   CCIfType<[i64],  CCAssignToReg<[R0, R1]>>,
+
+  // 32-bit floats
+  CCIfSubtarget<"hasFPU()", 
+      CCIfType<[f32], CCAssignToReg<[FR0, FR1, FR2, FR3]>>>,
+
+  CCAssignToStack<4, 4>
 ]>;
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
index 8b7c463a5ed41..2f5139f992e63 100644
--- a/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/SuperH/SuperHExpandPseudoInsts.cpp
@@ -26,6 +26,7 @@
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/Support/ErrorHandling.h"
+#include <cstddef>
 
 using namespace llvm;
 
@@ -101,7 +102,7 @@ void SuperHExpandPseudo::getStackOffset(Block &MBB, BlockIt MBBI, Register Frame
   const DebugLoc &DL = MBBI->getDebugLoc();
   const MachineFunction &MF = *MBB.getParent();
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-
+  MachineInstr &MI = *MBBI;
 
   // Split the stack up into indexable chunks, each instruction has
   // a fixed range that it can access, this range is positive only.
@@ -117,19 +118,42 @@ void SuperHExpandPseudo::getStackOffset(Block &MBB, BlockIt MBBI, Register Frame
   if (!STI->isLittleEndian() && Scale != 4)
     RealOffset -= 4-(Scale-1);
 
-  int64_t SpAdjust = AccessRange * (alignTo(RealOffset, Scale) / AccessRange);
-
-  // Expand sequence to
-  // mov      <frame reg>,  r1
-  // add      #-SpOffset,   r1
-  BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1).addReg(FrameReg);
-  if (SpAdjust != 0)
-    BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
-        .addReg(SH::R1)
-        .addImm(-SpAdjust);
-
   // Adjust the offset to be within the access range.
   Offset = RealOffset % AccessRange;
+
+  switch(MI.getOpcode()) {
+  case SH::MOVF32SF:
+  case SH::MOVF32LF: {
+
+    // Expand sequence to
+    // mov      <frame reg>,  r1
+    // add      (offset),     r1 ! Repeats until offset is reached.
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1)
+      .addReg(FrameReg);
+
+    ptrdiff_t OffsetLeft = RealOffset;
+    while(OffsetLeft != 0) {
+      int64_t V = OffsetLeft % 128;
+      BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+        .addImm(V);
+      OffsetLeft -= V;
+    }
+    break;
+  }
+  default: {
+
+    // Expand sequence to
+    // mov      <frame reg>,  r1
+    // add      #-SpOffset,   r1
+    int64_t SpAdjust = AccessRange * (alignTo(RealOffset, Scale) / AccessRange);  
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOV), SH::R1).addReg(FrameReg);
+    if (SpAdjust != 0)
+      BuildMI(MBB, MBBI, DL, TII->get(SH::ADDI), SH::R1)
+          .addReg(SH::R1)
+          .addImm(-SpAdjust);
+    break;
+  }
+  }
 }
 
 
@@ -186,6 +210,13 @@ bool SuperHExpandPseudo::storeToFrame(Block &MBB, BlockIt MBBI, int Scale) {
         .addImm(Offset);
     break;
   }
+  case SH::MOVF32SF: {
+
+    // fmov.s   <src reg>, @r1
+    BuildMI(MBB, MBBI, DL, TII->get(SH::FMOV_STORE))
+        .addReg(SH::R1, RegState::Kill)
+        .addReg(SrcReg, RegState::Kill);
+  }
   }
 
   return eraseMI(MI);
@@ -238,6 +269,13 @@ bool SuperHExpandPseudo::storeToAddress(Block &MBB, BlockIt MBBI) {
       Opc = SH::MOVLS4;
     break;
   }
+  case SH::MOVF32SP: {
+    if (Offset == 0)
+      Opc = SH::FMOV_STORE;
+    else
+      Opc = SH::FMOV_INDEX_STORE;
+    break;
+  }
   }
 
   // TODO: Allow bigger accesses.
@@ -276,6 +314,13 @@ bool SuperHExpandPseudo::expand<SH::MOVLSF>(Block &MBB, BlockIt MBBI) {
   return storeToFrame(MBB, MBBI, 4);
 }
 
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVF32SF>(Block &MBB, BlockIt MBBI) {
+
+  // Store to stack frame
+  return storeToFrame(MBB, MBBI, 4);
+}
+
 template <>
 bool SuperHExpandPseudo::expand<SH::MOVBSP>(Block &MBB, BlockIt MBBI) {
   
@@ -297,6 +342,13 @@ bool SuperHExpandPseudo::expand<SH::MOVLSP>(Block &MBB, BlockIt MBBI) {
   return storeToAddress(MBB, MBBI);
 }
 
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVF32SP>(Block &MBB, BlockIt MBBI) {
+
+  // Store to stack frame
+  return storeToFrame(MBB, MBBI, 4);
+}
+
 
 
 
@@ -352,6 +404,12 @@ bool SuperHExpandPseudo::loadFromFrame(Block &MBB, BlockIt MBBI, int Scale) {
         .addImm(Offset);
     break;
   }
+  case SH::MOVF32LF: {
+
+    // fmov.s   @r1, <dst reg>
+    BuildMI(MBB, MBBI, DL, TII->get(SH::FMOV_STORE), DstReg)
+        .addReg(SH::R1);
+  }
   }
 
   return eraseMI(MI);
@@ -405,6 +463,13 @@ bool SuperHExpandPseudo::loadFromAddress(Block &MBB, BlockIt MBBI) {
       Opc = SH::MOVLL4;
     break;
   }
+  case SH::MOVF32LP: {
+    if (Offset == 0)
+      Opc = SH::FMOV_LOAD;
+    else
+      Opc = SH::FMOV_INDEX_LOAD;
+    break;
+  }
   }
 
   // TODO: Allow bigger accesses.
@@ -441,6 +506,13 @@ bool SuperHExpandPseudo::expand<SH::MOVLLF>(Block &MBB, BlockIt MBBI) {
   return loadFromFrame(MBB, MBBI, 4);
 }
 
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVF32LF>(Block &MBB, BlockIt MBBI) {
+
+  // Load from stack frame.
+  return loadFromFrame(MBB, MBBI, 4);
+}
+
 template <>
 bool SuperHExpandPseudo::expand<SH::MOVBLP>(Block &MBB, BlockIt MBBI) {
 
@@ -462,6 +534,13 @@ bool SuperHExpandPseudo::expand<SH::MOVLLP>(Block &MBB, BlockIt MBBI) {
   return loadFromAddress(MBB, MBBI);
 }
 
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVF32LP>(Block &MBB, BlockIt MBBI) {
+
+  // Load from address.
+  return loadFromAddress(MBB, MBBI);
+}
+
 
 
 
@@ -500,6 +579,39 @@ bool SuperHExpandPseudo::expand<SH::MOVIL>(Block &MBB, BlockIt MBBI) {
   return loadFromImmediate(MBB, MBBI);
 }
 
+template <>
+bool SuperHExpandPseudo::expand<SH::MOVIF32>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+  auto DstReg = MI.getOperand(0).getReg();
+  auto Src = MI.getOperand(1);
+
+  if (Src.isFPImm()) {
+    if (Src.getFPImm()->isZero()) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::FLDI0), DstReg);
+      return eraseMI(MI);
+    }
+
+    if (Src.getFPImm()->isOne()) {
+      BuildMI(MBB, MBBI, DL, TII->get(SH::FLDI1), DstReg);
+      return eraseMI(MI);
+    }
+
+    llvm_unreachable("Invalid constant FP.");
+  } else if (Src.isCPI()) {
+
+    // Load to FPUL, assuming data is fr32, then move
+    // to destination register.
+    BuildMI(MBB, MBBI, DL, TII->get(SH::MOVLI), SH::R1)
+          .addConstantPoolIndex(MI.getOperand(1).getIndex());
+    BuildMI(MBB, MBBI, DL, TII->get(SH::LDSFPUL))
+          .addReg(SH::R1);
+    BuildMI(MBB, MBBI, DL, TII->get(SH::FSTS), DstReg);
+    return eraseMI(MI);
+  }
+  return false;
+}
+
 
 
 
@@ -652,6 +764,43 @@ bool SuperHExpandPseudo::expand<SH::SRArr>(Block &MBB, BlockIt MBBI) {
 
 
 
+//===----------------------------------------------------------------------===//
+//                                Conversion
+//===----------------------------------------------------------------------===//
+
+template <>
+bool SuperHExpandPseudo::expand<SH::F32TOI32>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+
+  auto SrcReg = MI.getOperand(1).getReg();
+  auto DstReg = MI.getOperand(2).getReg();
+
+  BuildMI(MBB, MBBI, DL, TII->get(SH::LDSFPUL))
+    .addReg(SrcReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::FLOAT32), DstReg);
+
+  return eraseMI(MI);
+}
+
+template <>
+bool SuperHExpandPseudo::expand<SH::I32TOF32>(Block &MBB, BlockIt MBBI) {
+  const DebugLoc &DL = MBBI->getDebugLoc();
+  MachineInstr &MI = *MBBI;
+
+  auto SrcReg = MI.getOperand(1).getReg();
+  auto DstReg = MI.getOperand(2).getReg();
+
+  BuildMI(MBB, MBBI, DL, TII->get(SH::FTRC32))
+    .addReg(SrcReg);
+  BuildMI(MBB, MBBI, DL, TII->get(SH::STSFPUL), DstReg);
+
+  return eraseMI(MI);
+}
+
+
+
+
 //===----------------------------------------------------------------------===//
 //                            General Interface
 //===----------------------------------------------------------------------===//
@@ -728,12 +877,19 @@ bool SuperHExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
     EXPAND(SH::MOVIB);
     EXPAND(SH::MOVIW);
     EXPAND(SH::MOVIL);
+    EXPAND(SH::MOVF32LF);
+    EXPAND(SH::MOVF32LP);
+    EXPAND(SH::MOVF32SP);
+    EXPAND(SH::MOVF32SF);
+    EXPAND(SH::MOVIF32);
     EXPAND(SH::SHLri);
     EXPAND(SH::SHRri);
     EXPAND(SH::SRAri);
     EXPAND(SH::SHLrr);
     EXPAND(SH::SHRrr);
     EXPAND(SH::SRArr);
+    EXPAND(SH::F32TOI32);
+    EXPAND(SH::I32TOF32);
   }
 #undef EXPAND
   return false;
diff --git a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
index 53e2e5eb733f5..be2051b52acfd 100644
--- a/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHFrameLowering.cpp
@@ -67,8 +67,7 @@ void SuperHFrameLowering::emitFrameAdjust(Register Base, MachineFunction &MF,
                                           MachineBasicBlock &MBB,
                                           MachineBasicBlock::iterator MBBI,
                                           int32_t AdjValue) const {
-  const SuperHInstrInfo &TII =
-      *static_cast<const SuperHInstrInfo *>(MF.getSubtarget().getInstrInfo());
+  const SuperHInstrInfo &TII = *MF.getSubtarget<SuperHSubtarget>().getInstrInfo();
   MachineInstr::MIFlag MFlag =
       AdjValue < 0 ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
   DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
diff --git a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
index 23f8068b24cfc..3266d9f7dc887 100644
--- a/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelDAGToDAG.cpp
@@ -41,6 +41,7 @@ namespace {
 
 /// Lowers LLVM IR (in DAG form) to SuperH MC instructions (in DAG form).
 class SuperHDAGToDAGISel : public SelectionDAGISel {
+  const SuperHSubtarget *Subtarget;
 public:
   SuperHDAGToDAGISel() = delete;
 
@@ -56,21 +57,6 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
   bool SelectFrAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
   bool SelectImm(SDNode *Op, SDValue N, SDValue &Value);
 
-  /// Return a target constant with the specified value of type i4.
-  inline SDValue getI4Imm(int64_t Imm, const SDLoc &DL) {
-    return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i4);
-  }
-
-  /// Return a target constant with the specified value of type i8.
-  inline SDValue getI8Imm(int64_t Imm, const SDLoc &DL) {
-    return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i8);
-  }
-
-  /// Return a target constant with the specified value of type i16.
-  inline SDValue getI16Imm(int64_t Imm, const SDLoc &DL) {
-    return CurDAG->getSignedTargetConstant(Imm, DL, MVT::i16);
-  }
-
 // Include the pieces autogenerated from the target description.
 #include "SuperHGenDAGISel.inc"
 
@@ -80,8 +66,6 @@ class SuperHDAGToDAGISel : public SelectionDAGISel {
   bool trySelect(SDNode *N);
 
   template <unsigned Opcode> bool trySelect(SDNode *N);
-
-  const SuperHSubtarget *Subtarget;
 };
 
 class SuperHDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
@@ -99,7 +83,7 @@ char SuperHDAGToDAGISelLegacy::ID = 0;
 INITIALIZE_PASS(SuperHDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
 
 bool SuperHDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
-  Subtarget = &MF.getSubtarget<SuperHSubtarget>();
+  Subtarget = &TM.getSubtarget<SuperHSubtarget>(MF.getFunction());
   return SelectionDAGISel::runOnMachineFunction(MF);
 }
 
@@ -124,7 +108,6 @@ bool SuperHDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
   MachineFunction &MF = CurDAG->getMachineFunction();
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
 
-
   switch(N.getOpcode()) {
   case SHISD::WRAPPER:
 
@@ -217,6 +200,15 @@ bool SuperHDAGToDAGISel::SelectImm(SDNode *Op, SDValue N, SDValue &Value) {
   MachineFunction &MF = CurDAG->getMachineFunction();
   SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
 
+  // Floating point values.
+  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N)) {
+    if (auto *CPV = SFI->tryGetConstant(C, *CurDAG, SHCP::no_modifier)) {
+      Value = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+      return true;
+    }
+  }
+
+  // Int constants.
   if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {
 
     // Constant would fit in immediate
@@ -279,7 +271,17 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::WRAPPER>(SDNode *N) {
     }
   }
 
-  // Constants
+  // FP Constants
+  if (ConstantFPSDNode *Const = dyn_cast<ConstantFPSDNode>(N0.getNode())) {
+    if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
+      SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
+      MachineSDNode *Res = CurDAG->getMachineNode(SH::MOVIF32, DL, MVT::f32, TGA);
+      ReplaceNode(N, Res);
+      return true;
+    }
+  }
+
+  // Int Constants
   if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N0.getNode())) {
     if (auto *CPV = SFI->tryGetConstant(Const, *CurDAG, SHCP::no_modifier)) {
       SDValue TGA = CurDAG->getTargetConstantPool(CPV, PtrVT, Align(4), 0);
@@ -305,6 +307,12 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
                           ->getZExtValue();
   SDLoc DL(N);
 
+  // Handle FP comparisons if enabled.
+  bool isFP32Cmp = 
+    Subtarget->hasFPU() &&
+    LHS.getSimpleValueType() == MVT::f32 && 
+    RHS.getSimpleValueType() == MVT::f32;
+
   // Comparison order is reverse in SuperH
   std::swap(LHS, RHS);
 
@@ -315,11 +323,17 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
   default:
     break;
   case SHCC::COND_EQ: {
-    Res = CurDAG->getMachineNode(SH::CMPEQ, DL, MVT::Glue, LHS, RHS);
+    if (isFP32Cmp)
+      Res = CurDAG->getMachineNode(SH::FCMP_EQ, DL, MVT::Glue, LHS, RHS);
+    else
+      Res = CurDAG->getMachineNode(SH::CMPEQ, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case SHCC::COND_GT: {
-    Res = CurDAG->getMachineNode(SH::CMPGT, DL, MVT::Glue, LHS, RHS);
+    if (isFP32Cmp)
+      Res = CurDAG->getMachineNode(SH::FCMP_GT, DL, MVT::Glue, LHS, RHS);
+    else
+      Res = CurDAG->getMachineNode(SH::CMPGT, DL, MVT::Glue, LHS, RHS);
     break;
   }
   case SHCC::COND_GE: {
@@ -357,6 +371,41 @@ template <> bool SuperHDAGToDAGISel::trySelect<SHISD::CMP>(SDNode *N) {
   return false;
 }
 
+template <> bool SuperHDAGToDAGISel::trySelect<SHISD::FCMP>(SDNode *N) {
+  SDValue LHS = N->getOperand(0);
+  SDValue RHS = N->getOperand(1);
+  SHCC::CondCode CC = (SHCC::CondCode)dyn_cast<ConstantSDNode>(N->getOperand(2))
+                          ->getZExtValue();
+  SDLoc DL(N);
+
+  // Comparison order is reverse in SuperH
+  std::swap(LHS, RHS);
+
+  // NOTE:  The comparisons just set the T bit, it's up to later instructions
+  //        to interpret the T bit as positive or negative.
+  SDNode *Res = nullptr;
+  switch (CC) {
+  default:
+    break;
+  case SHCC::COND_EQ: {
+    Res = CurDAG->getMachineNode(SH::FCMP_EQ, DL, MVT::Glue, LHS, RHS);
+    break;
+  }
+  case SHCC::COND_GT: {
+    Res = CurDAG->getMachineNode(SH::FCMP_GT, DL, MVT::Glue, LHS, RHS);
+    break;
+  }
+  }
+
+  if (Res) {
+    ReplaceUses(SDValue(N, 0), SDValue(Res, 0));
+    CurDAG->RemoveDeadNode(N);
+    return true;
+  }
+
+  return false;
+}
+
 template <> bool SuperHDAGToDAGISel::trySelect<SHISD::BRCOND>(SDNode *N) {
   SDValue Chain = N->getOperand(0);
   SDValue Dest = N->getOperand(1);
@@ -435,10 +484,11 @@ bool SuperHDAGToDAGISel::trySelect(SDNode *N) {
     return true;
   }
 
-    SELECT(ISD::FrameIndex);
-    SELECT(SHISD::WRAPPER);
-    SELECT(SHISD::BRCOND);
-    SELECT(SHISD::CMP);
+  SELECT(ISD::FrameIndex);
+  SELECT(SHISD::WRAPPER);
+  SELECT(SHISD::BRCOND);
+  SELECT(SHISD::CMP);
+  SELECT(SHISD::FCMP);
   }
 
 #undef SELECT
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
index 28a51c1a08364..ce2f14dbc8987 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.cpp
@@ -39,7 +39,7 @@
 
 using namespace llvm;
 
-#define DEBUG_TYPE "sh-lower"
+#define DEBUG_TYPE "sh-isel-lowering"
 
 SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
                                            const SuperHSubtarget &STI)
@@ -48,24 +48,15 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
 
   // GPR Registers are always 32 bit on SuperH.
   addRegisterClass(MVT::i32, &SH::GPRRegClass);
-  computeRegisterProperties(Subtarget->getRegisterInfo());
-
-  setSchedulingPreference(Sched::RegPressure);
-  setSupportsUnalignedAtomics(false);
-  setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
 
   // Loads and stores are legal
   for (MVT VT : MVT::integer_valuetypes()) {
     for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
       setLoadExtAction(N, VT, MVT::i1, Promote);
-      // setLoadExtAction(N, VT, MVT::i8, Expand);
-      // setLoadExtAction(N, VT, MVT::i16, Expand);
       setLoadExtAction(N, VT, MVT::i64, Expand);
     }
 
     setTruncStoreAction(VT, MVT::i1, Promote);
-    // setTruncStoreAction(VT, MVT::i8, Expand);
-    // setTruncStoreAction(VT, MVT::i16, Expand);
   }
 
   // Division and remainders are multi-instruction sequences
@@ -98,13 +89,41 @@ SuperHTargetLowering::SuperHTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::SETCC, MVT::i32, Custom);
   setOperationAction(ISD::SETCC, MVT::i64, Custom);
 
+  if (STI.hasFPU()) {
+    addRegisterClass(MVT::f32, &SH::FR32RegClass);
+
+    setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
+    setOperationAction(ISD::BR_CC, MVT::f32, Custom);
+    setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
+    setOperationAction(ISD::SETCC, MVT::f32, Custom);
+
+    if (STI.hasFP64()) {
+      addRegisterClass(MVT::f64, &SH::FR64RegClass);
+
+      setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
+      setOperationAction(ISD::BR_CC, MVT::f64, Custom);
+      setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
+      setOperationAction(ISD::SETCC, MVT::f64, Custom);
+    }
+  }
+
+
+  setStackPointerRegisterToSaveRestore(RegInfo->getStackRegister());
+  computeRegisterProperties(Subtarget->getRegisterInfo());
+
+  setSchedulingPreference(Sched::RegPressure);
   setBooleanContents(ZeroOrOneBooleanContent);
   setBooleanVectorContents(ZeroOrOneBooleanContent);
+  setSupportsUnalignedAtomics(false);
   setJumpIsExpensive(false);
   setMinFunctionAlignment(Align(4));
   setMinStackArgumentAlignment(Align(4));
 }
 
+bool SuperHTargetLowering::useSoftFloat() const {
+  return !Subtarget->hasFPU();
+}
+
 
 
 
@@ -148,96 +167,155 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue &LHS, SDValue &RHS,
   SDValue InCC;
   SHCC::CondCode SHcc = SHCC::COND_INVALID;
   SHCC::CondCode SHocc = SHCC::COND_T;
+  unsigned Opc;
 
-  switch (CC) {
-  default:
-    break;
-  case ISD::SETEQ: {
-    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
-      if (C->getSExtValue() == 0) {
-        SHcc = SHCC::COND_Z;
-        SHocc = SHCC::COND_T;
-        break;
-      }
+  if (Subtarget->hasFPU() &&
+      LHS.getSimpleValueType().isFloatingPoint() && 
+      RHS.getSimpleValueType().isFloatingPoint()) {
+
+    switch (CC) {
+    default:
+      break;
+    case ISD::SETOEQ:
+    case ISD::SETUEQ:
+    case ISD::SETEQ: {
+      SHcc = SHCC::COND_EQ;
+      SHocc = SHCC::COND_T;
+      break;
     }
-    SHcc = SHCC::COND_EQ;
-    SHocc = SHCC::COND_T;
-    break;
-  }
-  case ISD::SETNE: {
-    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
-      if (C->getSExtValue() == 0) {
-        SHcc = SHCC::COND_Z;
-        SHocc = SHCC::COND_F;
-        break;
-      }
+    case ISD::SETONE:
+    case ISD::SETUNE:
+    case ISD::SETNE: {
+      SHcc = SHCC::COND_EQ;
+      SHocc = SHCC::COND_F;
+      break;
     }
-    SHcc = SHCC::COND_EQ;
-    SHocc = SHCC::COND_F;
-    break;
-  }
-  case ISD::SETLT: {
-    // Swap operands and reverse the branching condition.
-    std::swap(LHS, RHS);
-    SHcc = SHCC::COND_GE;
-    SHocc = SHCC::COND_F;
-    break;
-  }
-  case ISD::SETLE: {
-    // Swap operands and reverse the branching condition.
-    std::swap(LHS, RHS);
-    SHcc = SHCC::COND_GT;
-    SHocc = SHCC::COND_F;
-    break;
-  }
-  case ISD::SETGT: {
-    if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
-      switch (C->getSExtValue()) {
-      case -1: {
-        SHcc = SHCC::COND_PZ;
-        SHocc = SHCC::COND_T;
-        break;
+    case ISD::SETOGT:
+    case ISD::SETUGT:
+    case ISD::SETGT: {
+      SHcc = SHCC::COND_GT;
+      SHocc = SHCC::COND_T;
+      break;
+    }
+    case ISD::SETOLT:
+    case ISD::SETULT:
+    case ISD::SETLT: {
+      std::swap(LHS, RHS);
+      SHcc = SHCC::COND_GT;
+      SHocc = SHCC::COND_T;
+      break;
+    }
+    case ISD::SETOGE:
+    case ISD::SETUGE:
+    case ISD::SETGE: {
+      std::swap(LHS, RHS);
+      SHcc = SHCC::COND_GT;
+      SHocc = SHCC::COND_F;
+      break;
+    }
+    case ISD::SETOLE:
+    case ISD::SETULE:
+    case ISD::SETLE: {
+      SHcc = SHCC::COND_GT;
+      SHocc = SHCC::COND_F;
+      break;
+    }
+    }
+    
+    Opc = SHISD::FCMP;
+  } else {
+    switch (CC) {
+    default:
+      break;
+    case ISD::SETEQ: {
+      if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
+        if (C->getSExtValue() == 0) {
+          SHcc = SHCC::COND_Z;
+          SHocc = SHCC::COND_T;
+          break;
+        }
       }
-      case 0: {
-        SHcc = SHCC::COND_PL;
-        SHocc = SHCC::COND_T;
-        break;
+      SHcc = SHCC::COND_EQ;
+      SHocc = SHCC::COND_T;
+      break;
+    }
+    case ISD::SETNE: {
+      if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
+        if (C->getSExtValue() == 0) {
+          SHcc = SHCC::COND_Z;
+          SHocc = SHCC::COND_F;
+          break;
+        }
       }
+      SHcc = SHCC::COND_EQ;
+      SHocc = SHCC::COND_F;
+      break;
+    }
+    case ISD::SETLT: {
+      // Swap operands and reverse the branching condition.
+      std::swap(LHS, RHS);
+      SHcc = SHCC::COND_GE;
+      SHocc = SHCC::COND_F;
+      break;
+    }
+    case ISD::SETLE: {
+      // Swap operands and reverse the branching condition.
+      std::swap(LHS, RHS);
+      SHcc = SHCC::COND_GT;
+      SHocc = SHCC::COND_F;
+      break;
+    }
+    case ISD::SETGT: {
+      if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
+        switch (C->getSExtValue()) {
+        case -1: {
+          SHcc = SHCC::COND_PZ;
+          SHocc = SHCC::COND_T;
+          break;
+        }
+        case 0: {
+          SHcc = SHCC::COND_PL;
+          SHocc = SHCC::COND_T;
+          break;
+        }
+        }
       }
+      SHcc = SHCC::COND_GT;
+      SHocc = SHCC::COND_T;
+      break;
     }
-    SHcc = SHCC::COND_GT;
-    SHocc = SHCC::COND_T;
-    break;
-  }
-  case ISD::SETGE: {
-    SHcc = SHCC::COND_GE;
-    SHocc = SHCC::COND_T;
-    break;
-  }
-  case ISD::SETUGT: {
-    SHcc = SHCC::COND_HI;
-    SHocc = SHCC::COND_T;
-    break;
-  }
-  case ISD::SETUGE: {
-    SHcc = SHCC::COND_HS;
-    SHocc = SHCC::COND_T;
-    break;
-  }
-  case ISD::SETULT: {
-    // Swap operands and reverse the branching condition.
-    std::swap(LHS, RHS);
-    SHcc = SHCC::COND_HS;
-    SHocc = SHCC::COND_F;
-    break;
-  }
-  case ISD::SETULE: {
-    // Swap operands and reverse the branching condition.
-    std::swap(LHS, RHS);
-    SHcc = SHCC::COND_HI;
-    SHocc = SHCC::COND_F;
-    break;
-  }
+    case ISD::SETGE: {
+      SHcc = SHCC::COND_GE;
+      SHocc = SHCC::COND_T;
+      break;
+    }
+    case ISD::SETUGT: {
+      SHcc = SHCC::COND_HI;
+      SHocc = SHCC::COND_T;
+      break;
+    }
+    case ISD::SETUGE: {
+      SHcc = SHCC::COND_HS;
+      SHocc = SHCC::COND_T;
+      break;
+    }
+    case ISD::SETULT: {
+      // Swap operands and reverse the branching condition.
+      std::swap(LHS, RHS);
+      SHcc = SHCC::COND_HS;
+      SHocc = SHCC::COND_F;
+      break;
+    }
+    case ISD::SETULE: {
+      // Swap operands and reverse the branching condition.
+      std::swap(LHS, RHS);
+      SHcc = SHCC::COND_HI;
+      SHocc = SHCC::COND_F;
+      break;
+    }
+    }
+    
+    Opc = SHISD::CMP;
   }
 
   LLVM_DEBUG(dbgs() << "Lowered CC " << CC << " to " 
@@ -246,7 +324,7 @@ SDValue SuperHTargetLowering::getSHCmp(SDValue &LHS, SDValue &RHS,
 
   InCC = DAG.getTargetConstant(SHcc, DL, MVT::i8);
   OutCC = DAG.getTargetConstant(SHocc, DL, MVT::i8);
-  return DAG.getNode(SHISD::CMP, DL, MVT::Glue, LHS, RHS, InCC);
+  return DAG.getNode(Opc, DL, MVT::Glue, LHS, RHS, InCC);
 }
 
 SDValue SuperHTargetLowering::LowerSELECT_CC(SDValue Op,
@@ -345,6 +423,14 @@ SDValue SuperHTargetLowering::LowerConstant(SDValue Op,
     SDValue Const = DAG.getTargetConstant(*C->getConstantIntValue(), DL, C->getValueType(0));
     return DAG.getNode(SHISD::WRAPPER, DL, C->getValueType(0), Const);
   }
+  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Op)) {
+    auto DL = SDLoc(C);
+
+    // lower to constpool.
+    SDValue Const = DAG.getTargetConstantFP(*C->getConstantFPValue(), DL, C->getValueType(0));
+    return DAG.getNode(SHISD::WRAPPER, DL, C->getValueType(0), Const);
+  }
+
   return SDValue();
 }
 
@@ -442,6 +528,8 @@ SDValue SuperHTargetLowering::LowerFormalArguments(
         RC = &SH::GPRRegClass;
       } else if (RegVT == MVT::i32) {
         RC = &SH::GPRRegClass;
+      } else if (RegVT == MVT::f32) {
+        RC = &SH::FR32RegClass;
       } else {
         llvm_unreachable("Unknown argument type!");
       }
@@ -547,6 +635,9 @@ SuperHTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
     CCValAssign &VA = RVLocs[i];
     SDValue OutVal = OutVals[i];
 
+    if (!VA.isRegLoc())
+      break;
+
     // Promote values to the appropriate types.
     switch(VA.getLocInfo()) {
     case CCValAssign::SExt:
@@ -948,6 +1039,7 @@ SDValue SuperHTargetLowering::LowerOperation(SDValue Op,
   case ISD::MUL:
     return LowerMUL(Op, DAG);
   case ISD::Constant:
+  case ISD::ConstantFP:
     return LowerConstant(Op, DAG);
   case ISD::GlobalAddress:
     return LowerGlobalAddress(Op, DAG);
@@ -1078,6 +1170,7 @@ MachineBasicBlock *SuperHTargetLowering::EmitInstrWithCustomInserter(
   case SH::Select8:
   case SH::Select16:
   case SH::Select32:
+  case SH::SelectF32:
     return insertSELECTCC(MI, MBB);
   }
 
diff --git a/llvm/lib/Target/SuperH/SuperHISelLowering.h b/llvm/lib/Target/SuperH/SuperHISelLowering.h
index 77100366b8f41..d6e8aaef9cb0b 100644
--- a/llvm/lib/Target/SuperH/SuperHISelLowering.h
+++ b/llvm/lib/Target/SuperH/SuperHISelLowering.h
@@ -31,6 +31,9 @@ class SuperHTargetLowering : public TargetLowering {
 public:
   SuperHTargetLowering(const TargetMachine &TM, const SuperHSubtarget &STI);
 
+  // Whether to use software floating point
+  bool useSoftFloat() const override;
+
   /// ReplaceNodeResults - Replace a node with an illegal result type
   /// with a new node built out of custom code.
   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
@@ -89,8 +92,6 @@ class SuperHTargetLowering : public TargetLowering {
 private:
   MachineBasicBlock *insertSELECTCC(MachineInstr &MI,
                                     MachineBasicBlock *BB) const;
-  MachineBasicBlock *insertLoad(MachineInstr &MI, MachineBasicBlock *BB) const;
-  MachineBasicBlock *insertStore(MachineInstr &MI, MachineBasicBlock *BB) const;
 
   SDValue getPICJumpTableRelocBase(SDValue Table,
                                    SelectionDAG &DAG) const override;
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFPU.td b/llvm/lib/Target/SuperH/SuperHInstrFPU.td
new file mode 100644
index 0000000000000..f3f99b66dcd0c
--- /dev/null
+++ b/llvm/lib/Target/SuperH/SuperHInstrFPU.td
@@ -0,0 +1,394 @@
+//===-- SuperHInstrDSP.td - DSP SuperH Instruction Definition --*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-------------------------------------------------------------------------===//
+///
+/// \file
+/// This file describes the FPU extensions for the SuperH Instruction Set.
+///
+//===-------------------------------------------------------------------------===//
+
+def SHSDT_FCmp       : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, i8>]>;
+def SHfcmp           : SDNode<"SHISD::FCMP", SHSDT_FCmp, [SDNPOutGlue]>;
+
+let Predicates = [HasFPU] in {
+
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                          Data Transfer Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+// fmov FRm, FRn
+let isMoveReg = 1, hasSideEffects = 0 in
+def FMOV              : InstRmRn<0b1111000000001100,
+                                (outs FR32:$Rn), (ins FR32:$Rm),
+                                "fmov $Rm,$Rn",
+                                []>;
+
+
+
+
+//===--------------------------------------------------------------------------===//
+// Load Instructions
+//===--------------------------------------------------------------------------===//
+
+let hasSideEffects = 0, mayLoad = 1 in {
+
+// fmov.s @Rm, FRn                     
+def FMOV_LOAD         : InstRmRn<0b1111000000001000,
+                                (outs FR32:$Rn), (ins IGPR:$Rm),
+                                "fmov.s $Rm,$Rn",
+                                []>;
+
+// fmov.s @Rm+, FRn                     
+def FMOV_RESTORE      : InstRmRn<0b1111000000001001,
+                                (outs FR32:$Rn), (ins IGPRInc:$Rm),
+                                "fmov.s $Rm,$Rn",
+                                []>;
+
+// fmov.s @(R0,Rm), FRn                     
+def FMOV_INDEX_LOAD   : InstRmRn<0b1111000000000110,
+                                (outs FR32:$Rn), (ins IGPR:$Rm),
+                                "fmov.s $Rm,$Rn",
+                                []>;
+}
+
+//===--------------------------------------------------------------------------===//
+// Store Instructions
+//===--------------------------------------------------------------------------===//
+
+let hasSideEffects = 0, mayStore = 1 in {
+
+// fmov.s FRm, @Rn                     
+def FMOV_STORE        : InstRmRn<0b1111000000001010,
+                                (outs), (ins FR32:$Rm, IGPR:$Rn),
+                                "fmov.s $Rm,$Rn",
+                                []>;
+
+// fmov.s FRm, @-Rn                     
+def FMOV_SAVE         : InstRmRn<0b1111000000001011,
+                                (outs), (ins FR32:$Rm, IGPRDec:$Rn),
+                                "fmov.s $Rm,$Rn",
+                                []>;
+
+// fmov.s FRm, @(R0,Rn)                    
+def FMOV_INDEX_STORE  : InstRmRn<0b1111000000000111,
+                                (outs), (ins FR32:$Rm, IGPR:$Rn),
+                                "fmov.s $Rm,$Rn",
+                                []>;
+
+}
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                  Floating-Point Single-Precision Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+// fldi0 FRn
+def FLDI0               : InstRn<0b1111000010001101,
+                                (outs FR32:$Rn), (ins),
+                                "fldi0 $Rn",
+                                []>;
+
+// fldi1 FRn
+def FLDI1               : InstRn<0b1111000010011101,
+                                (outs FR32:$Rn), (ins),
+                                "fldi1 $Rn",
+                                []>;
+
+// flds FRm,fpul
+let Defs = [FPUL] in
+def FLDS                : InstRm<0b1111000000011101,
+                                (outs), (ins FR32:$Rm),
+                                "flds $Rm,fpul",
+                                []>;
+
+// fsts fpul,FRn
+let Uses = [FPUL] in
+def FSTS                : InstRn<0b1111000000001101,
+                                (outs FR32:$Rn), (ins),
+                                "fsts fpul,$Rn",
+                                []>;
+
+// fabs FRn
+let Constraints = "$src = $Rn" in
+def FABS                : InstRn<0b1111000001011101,
+                                (outs FR32:$Rn), (ins FR32:$src),
+                                "fabs $Rn",
+                                [(set f32:$Rn, (fabs f32:$src))]>;
+
+// fneg FRn
+let Constraints = "$src = $Rn" in
+def FNEG                : InstRn<0b1111000001001101,
+                                (outs FR32:$Rn), (ins FR32:$src),
+                                "fneg $Rn",
+                                [(set f32:$Rn, (fneg f32:$src))]>;
+
+// fadd FRm,FRn
+let Constraints = "$src = $Rn" in
+def FADD              : InstRmRn<0b1111000000000000,
+                                (outs FR32:$Rn), (ins FR32:$Rm, FR32:$src),
+                                "fadd $Rm,$Rn",
+                                [(set f32:$Rn, (fadd f32:$Rm, f32:$src))]>;
+
+// fsub FRm,FRn
+let Constraints = "$src = $Rn" in
+def FSUB              : InstRmRn<0b1111000000000001,
+                                (outs FR32:$Rn), (ins FR32:$Rm, FR32:$src),
+                                "fsub $Rm,$Rn",
+                                [(set f32:$Rn, (fsub f32:$Rm, f32:$src))]>;
+
+// fmul FRm,FRn
+let Constraints = "$src = $Rn" in
+def FMUL              : InstRmRn<0b1111000000000010,
+                                (outs FR32:$Rn), (ins FR32:$Rm, FR32:$src),
+                                "fmul $Rm,$Rn",
+                                [(set f32:$Rn, (fmul f32:$Rm, f32:$src))]>;
+
+// fmac fr0,FRm,FRn
+let Defs = [FR0] in
+def FMAC              : InstRmRn<0b1111000000001110,
+                                (outs FR32:$Rn), (ins FR32:$Rm),
+                                "fmac fr0,$Rm,$Rn",
+                                []>;
+
+// fdiv FRm,FRn
+let Constraints = "$src = $Rn" in
+def FDIV              : InstRmRn<0b1111000000000011,
+                                (outs FR32:$Rn), (ins FR32:$Rm, FR32:$src),
+                                "fdiv $Rm,$Rn",
+                                [(set f32:$Rn, (fdiv f32:$Rm, f32:$src))]>;
+
+// fsqrt FRn
+let Constraints = "$src = $Rn" in
+def FSQRT               : InstRn<0b1111000001101101,
+                                (outs FR32:$Rn), (ins FR32:$src),
+                                "fsqrt $Rn",
+                                [(set f32:$Rn, (fsqrt f32:$src))]>;
+
+// fcmp/eq FRm,FRn
+let isCompare = 1, Defs = [SR] in
+def FCMP_EQ           : InstRmRn<0b1111000000000100,
+                                (outs), (ins FR32:$Rm, FR32:$Rn),
+                                "fcmp/eq $Rm,$Rn",
+                                []>;
+
+// fcmp/gt FRm,FRn
+let isCompare = 1, Defs = [SR] in
+def FCMP_GT           : InstRmRn<0b1111000000000101,
+                                (outs), (ins FR32:$Rm, FR32:$Rn),
+                                "fcmp/eq $Rm,$Rn",
+                                []>;
+
+// float fpul,FRn
+let Uses = [FPUL] in
+def FLOAT32             : InstRn<0b1111000000101101,
+                                (outs FR32:$Rn), (ins),
+                                "float fpul,$Rn",
+                                []>;
+
+// ftrc fpul,FRn
+let Defs = [FPUL] in
+def FTRC32             : InstRm<0b1111000000111101,
+                                (outs), (ins FR32:$Rm),
+                                "ftrc $Rm,fpul",
+                                []>;
+
+// fipr FVm,FVn
+def FIPR            : InstFVmFVn<0b1111000011101101,
+                                (outs VEC128:$Rn), (ins VEC128:$Rm),
+                                "fipr $Rm,$Rn",
+                                []>;
+
+// fipr FVm,FVn
+let Uses = [XMTRX] in
+def FTRV               : InstFVn<0b1111000111111101,
+                                (outs VEC128:$Rn), (ins),
+                                "ftrv xmtrx,$Rn",
+                                []>;
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                      Floating-Point Control Instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+// lds Rm,fpscr
+let Defs = [FPSCR] in
+def LDSFPSCR            : InstRm<0b0100000001101010,
+                                (outs), (ins GPR:$Rm),
+                                "lds $Rm,fpscr",
+                                []>;
+
+// sts fpscr,Rn
+let Uses = [FPSCR] in
+def STSFPSCR            : InstRn<0b0000000001101010,
+                                (outs GPR:$Rn), (ins),
+                                "sts fpscr,$Rn",
+                                []>;
+
+// lds @Rm+,fpscr
+let Defs = [FPSCR] in
+def LDSMFPSCR           : InstRm<0b0100000001100110,
+                                (outs), (ins IGPRInc:$Rm),
+                                "lds $Rm,fpscr",
+                                []>;
+
+// sts fpscr, at -Rn
+let Uses = [FPSCR] in
+def STSMFPSCR           : InstRn<0b0100000001100010,
+                                (outs IGPRDec:$Rn), (ins),
+                                "sts fpscr,$Rn",
+                                []>;
+
+// lds Rm,fpul
+let Defs = [FPUL] in
+def LDSFPUL             : InstRm<0b0100000001011010,
+                                (outs), (ins GPR:$Rm),
+                                "lds $Rm,fpul",
+                                []>;
+
+// sts fpul,Rn
+let Uses = [FPUL] in
+def STSFPUL             : InstRn<0b0000000001011010,
+                                (outs GPR:$Rn), (ins),
+                                "sts fpul,$Rn",
+                                []>;
+
+// lds @Rm+,fpul
+let Defs = [FPUL] in
+def LDSMFPUL            : InstRm<0b0100000001010110,
+                                (outs), (ins IGPRInc:$Rm),
+                                "lds $Rm,fpul",
+                                []>;
+
+// sts fpul, at -Rn
+let Uses = [FPUL] in
+def STSMFPUL            : InstRn<0b0100000001010010,
+                                (outs IGPRDec:$Rn), (ins),
+                                "sts fpul,$Rn",
+                                []>;
+
+// frchg
+let Defs = [FPSCR] in
+def FRCHG                 : Inst<0b1111101111111101,
+                                (outs), (ins),
+                                "frchg",
+                                []>;
+
+// fschg
+let Defs = [FPSCR] in
+def FSCHG                 : Inst<0b1111001111111101,
+                                (outs), (ins),
+                                "fschg",
+                                []>;
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                              Pseudo instructions
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+//===--------------------------------------------------------------------------===//
+// Load/Store
+//===--------------------------------------------------------------------------===//
+
+
+
+
+def MOVF32LF  : SHLoadPseudo<(outs FR32:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVF32LF $src, $Rn",
+                            []>;
+
+def MOVF32LP  : SHLoadPseudo<(outs FR32:$Rn), (ins (memri $Rm, $disp):$src),
+                            "! MOVF32LP $src, $Rn",
+                            []>;
+
+def MOVF32SF  : SHStorePseudo<(outs), (ins FR32:$src, (memri $Rm, $disp):$dst),
+                             "! MOVF32SF $src, $dst",
+                             []>;
+
+def MOVF32SP  : SHStorePseudo<(outs), (ins FR32:$src, (memri $Rm, $disp):$dst),
+                             "! MOVF32SP $src, $dst",
+                             []>;
+
+def MOVIF32       : SHPseudo<(outs FR32:$dst), (ins f32imm:$src),
+                             "! MOVIF32 $src, $dst",
+                             [(set f32:$dst, anyimmf32:$src)]>;
+
+
+
+
+//===--------------------------------------------------------------------------===//
+// Conversion
+//===--------------------------------------------------------------------------===//
+
+def F32TOI32 : SHPseudo<(outs GPR:$dst), (ins FR32:$src),
+                             "! F32TOI32 $src, $dst",
+                             []>;
+
+def I32TOF32 : SHPseudo<(outs FR32:$dst), (ins GPR:$src),
+                             "! I32TOF32 $src, $dst",
+                             []>;
+
+
+
+
+//===--------------------------------------------------------------------------===//
+// Selection
+//===--------------------------------------------------------------------------===//
+
+def SelectF32   : SHSelectPseudo<(outs FR32:$dst),
+                                (ins FR32:$src, FR32:$src2, i8imm:$cc),
+                                "! SelectF32 PSEUDO",
+                                [(set f32:$dst,
+                                 (SHselectcc f32:$src, f32:$src2, timm:$cc))]>;
+}
+
+
+
+
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+//                           Non-instruction patterns
+//===--------------------------------------------------------------------------===//
+//===--------------------------------------------------------------------------===//
+
+def : Pat<(i32 (fp_to_sint (f32  FR32:$src))),  (F32TOI32  FR32:$src)>;
+def : Pat<(f32 (sint_to_fp (i32   GPR:$src))),  (I32TOF32   GPR:$src)>;
+
+//===--------------------------------------------------------------------------===//
+// Loads
+//===--------------------------------------------------------------------------===//
+
+def : Pat<(f32 (load          IGPR:$src)),    (FMOV_LOAD    IGPR:$src)>;
+def : Pat<(f32 (load          addr:$src)),    (MOVF32LP     addr:$src)>;
+def : Pat<(f32 (load        fraddr:$src)),    (MOVF32LF   fraddr:$src)>;
+def : Pat<(f32 (extloadf32    IGPR:$src)),    (FMOV_LOAD    IGPR:$src)>;
+def : Pat<(f32 (extloadf32    addr:$src)),    (MOVF32LP     addr:$src)>;
+def : Pat<(f32 (extloadf32  fraddr:$src)),    (MOVF32LF   fraddr:$src)>;
+
+//===--------------------------------------------------------------------------===//
+// Stores
+//===--------------------------------------------------------------------------===//
+def : Pat<(store           f32:$src,    GPR:$dst),  (FMOV_STORE FR32:$src,     GPR:$dst)>;
+def : Pat<(store           f32:$src,   addr:$dst),  (MOVF32SP   FR32:$src,    addr:$dst)>;
+def : Pat<(store           f32:$src, fraddr:$dst),  (MOVF32SF   FR32:$src,  fraddr:$dst)>;
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrFormats.td b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
index 11ad66fe6a24a..fb57257c9767e 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrFormats.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrFormats.td
@@ -309,4 +309,40 @@ class InstD12<bits<16> opcode, dag outs, dag ins, string asmstr, list<dag> patte
   // Operands
   bits<12> disp;
   let Inst{11-0} = disp;
+}
+
+//===----------------------------------------------------------------------===//
+// Register -> (Any) Instruction
+// <opop|rn|opopopopop>
+//===----------------------------------------------------------------------===//
+class InstFVn<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{10-0} = Opcode{10-0};
+
+  // Operands
+  bits<2> Rn;
+  let Inst{11-10} = Rn;
+}
+
+//===----------------------------------------------------------------------===//
+// Register -> (Any) Instruction
+// <opop|rn|rm|opopopopop>
+//===----------------------------------------------------------------------===//
+class InstFVmFVn<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<2> Rm;
+  bits<2> Rn;
+  let Inst{11-10} = Rn{1-0};
+  let Inst{9-8} = Rm{1-0};
 }
\ No newline at end of file
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
index 1bbc822a33d46..250b67effcd10 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.cpp
@@ -44,7 +44,7 @@ using namespace llvm;
 
 SuperHInstrInfo::SuperHInstrInfo(const SuperHSubtarget &ST)
     : SuperHGenInstrInfo(ST, RI, SH::ADJCALLSTACKDOWN, SH::ADJCALLSTACKUP),
-      RI(ST), Subtarget(ST) {}
+      STI(ST), RI(ST) {}
 
 // Pin the vtable to this file.
 void SuperHInstrInfo::anchor() {}
@@ -199,6 +199,33 @@ void SuperHInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
     return;
   };
 
+  // GPR -> FR32
+  if (SH::GPRRegClass.contains(SrcReg) && 
+      SH::FR32RegClass.contains(DestReg)) {
+
+    BuildMI(MBB, MI, DL, get(SH::LDSFPUL))
+        .addReg(SrcReg, getKillRegState(KillSrc));
+    BuildMI(MBB, MI, DL, get(SH::FSTS), DestReg);
+    return;
+  }
+
+  // FR32 -> GPR
+  if (SH::FR32RegClass.contains(SrcReg) && 
+      SH::GPRRegClass.contains(DestReg)) {
+    
+    BuildMI(MBB, MI, DL, get(SH::FLDS))
+        .addReg(SrcReg, getKillRegState(KillSrc));
+    BuildMI(MBB, MI, DL, get(SH::STSFPUL), DestReg);
+    return;
+  }
+
+  // FR32 -> FR32
+  if (SH::FR32RegClass.contains(SrcReg, DestReg)) {
+    BuildMI(MBB, MI, DL, get(SH::FMOV), DestReg)
+        .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  }
+
   // Otherwise this is not possible.
   llvm_unreachable("Impossible reg-to-reg copy");
 }
@@ -231,18 +258,28 @@ void SuperHInstrInfo::storeRegToStackSlot(
                     << "\n");
 
   unsigned Opc;
-  switch (ObjectSize) {
-  default:
-    llvm_unreachable("Cannot store this register into stack slot!");
-  case 1:
-    Opc = SH::MOVBSF;
-    break;
-  case 2:
-    Opc = SH::MOVWSF;
-    break;
-  case 4:
-    Opc = SH::MOVLSF;
-    break;
+
+  if (SH::FR32RegClass.contains(SrcReg)) {
+
+    // F32 Registers.
+    Opc = SH::MOVF32SF;
+  } else {
+
+    // Integer registers.
+    switch (ObjectSize) {
+    default:
+      llvm_unreachable("Cannot store this register into stack slot!");
+    case 1:
+      Opc = SH::MOVBSF;
+      break;
+    case 2:
+      Opc = SH::MOVWSF;
+      break;
+    case 4:
+      Opc = SH::MOVLSF;
+
+      break;
+    }
   }
   BuildMI(MBB, II, DebugLoc(), get(Opc))
       .addReg(SrcReg, getKillRegState(isKill))
@@ -276,18 +313,25 @@ void SuperHInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
              << " from slot " << FrameIndex << " size=" << ObjectSize << "\n");
 
   unsigned Opc;
-  switch (ObjectSize) {
-  default:
-    llvm_unreachable("Cannot load this register from stack slot!");
-  case 1:
-    Opc = SH::MOVBLF;
-    break;
-  case 2:
-    Opc = SH::MOVWLF;
-    break;
-  case 4:
-    Opc = SH::MOVLLF;
-    break;
+
+  if (SH::FR32RegClass.contains(DestReg)) {
+
+    // F32 Registers.
+    Opc = SH::MOVF32LF;
+  } else {
+    switch (ObjectSize) {
+    default:
+      llvm_unreachable("Cannot load this register from stack slot!");
+    case 1:
+      Opc = SH::MOVBLF;
+      break;
+    case 2:
+      Opc = SH::MOVWLF;
+      break;
+    case 4:
+      Opc = SH::MOVLLF;
+      break;
+    }
   }
 
   BuildMI(MBB, II, DebugLoc(), get(Opc), DestReg)
diff --git a/llvm/lib/Target/SuperH/SuperHInstrInfo.h b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
index 9b6cb9a2ea49c..6987306481716 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.h
@@ -65,8 +65,8 @@ static StringRef getCondName(CondCode CC) {
 } // end of namespace SHCC
 
 class SuperHInstrInfo : public SuperHGenInstrInfo {
+  const SuperHSubtarget &STI;
   const SuperHRegisterInfo RI;
-  const SuperHSubtarget &Subtarget;
   virtual void anchor();
 
 public:
@@ -134,8 +134,6 @@ class SuperHInstrInfo : public SuperHGenInstrInfo {
   bool isBranchOffsetInRange(unsigned BranchOpc,
                              int64_t BrOffset) const override;
 };
-
-const SuperHInstrInfo *createSuperHInstrInfo(const SuperHSubtarget &STI);
 } // namespace llvm
 
 #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 d83a1e8add66a..5519d0e485315 100644
--- a/llvm/lib/Target/SuperH/SuperHInstrInfo.td
+++ b/llvm/lib/Target/SuperH/SuperHInstrInfo.td
@@ -243,49 +243,11 @@ def fraddr : ComplexPattern<iPTR, 2, "SelectFrAddr">;
 def anyimm8 : ComplexPattern<i8, 1, "SelectImm", [imm]>;
 def anyimm16 : ComplexPattern<i16, 1, "SelectImm", [imm]>;
 def anyimm32 : ComplexPattern<i32, 1, "SelectImm", [imm]>;
+def anyimmf32 : ComplexPattern<f32, 1, "SelectImm", [imm]>;
 }
 
 
 
-//===--------------------------------------------------------------------------===//
-// Predicates
-//===--------------------------------------------------------------------------===//
-
-def HasFSCA     : Predicate<"Subtarget->hasFSCA()">,
-                  AssemblerPredicate<(all_of FeatureFSCA)>;
-
-def HasFSRRA    : Predicate<"Subtarget->hasFSRRA()">,
-                  AssemblerPredicate<(all_of FeatureFSRRA)>;
-
-def HasFPU      : Predicate<"Subtarget->hasFPU()">,
-                  AssemblerPredicate<(all_of FeatureFPU)>;
-
-def HasDSP      : Predicate<"Subtarget->hasDSP()">,
-                  AssemblerPredicate<(all_of FeatureDSP)>;
-
-def HasSH2      : Predicate<"Subtarget->hasSH2Inst()">,
-                  AssemblerPredicate<(all_of FeatureSH2)>;
-
-def HasSH2E     : Predicate<"Subtarget->hasSH2EInst()">,
-                  AssemblerPredicate<(all_of FeatureSH2E)>;
-
-def HasSH2A     : Predicate<"Subtarget->hasSH2AInst()">,
-                  AssemblerPredicate<(all_of FeatureSH2A)>;
-
-def HasSH3      : Predicate<"Subtarget->hasSH3Inst()">,
-                  AssemblerPredicate<(all_of FeatureSH3)>;
-
-def HasSH3E     : Predicate<"Subtarget->hasSH3EInst()">,
-                  AssemblerPredicate<(all_of FeatureSH3E)>;
-
-def HasSH4      : Predicate<"Subtarget->hasSH4Inst()">,
-                  AssemblerPredicate<(all_of FeatureSH4)>;
-
-def HasSH4A     : Predicate<"Subtarget->hasSH4AInst()">,
-                  AssemblerPredicate<(all_of FeatureSH4A)>;  
-
-
-
 
 //===--------------------------------------------------------------------------===//
 // Condition Codes
@@ -1403,7 +1365,7 @@ def TRAPA             : InstI8<0b1100001100000000,
 //===--------------------------------------------------------------------------===//
 
 include "SuperHInstrDSP.td"
-
+include "SuperHInstrFPU.td"
 
 //===--------------------------------------------------------------------------===//
 //===--------------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
index 944f196aa250b..b7324334088c8 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.cpp
@@ -130,6 +130,35 @@ SuperHMachineFunctionInfo::tryGetConstant(ConstantSDNode *N, SelectionDAG &DAG,
       Modifier);
 }
 
+SuperHConstantPoolConstant *
+SuperHMachineFunctionInfo::tryGetConstant(ConstantFPSDNode *N, SelectionDAG &DAG,
+                                          SHCP::SHCPModifier Modifier) {
+
+  // Early exit for null node.
+  if (!N)
+    return nullptr;
+
+  // Run though the constant pool that is tied to the DAG and search for
+  // the constant there.
+  MachineConstantPool *MCP = DAG.getMachineFunction().getConstantPool();
+  for (auto &MC : MCP->getConstants()) {
+    if (MC.isMachineConstantPoolEntry()) {
+      if (auto *CPV = (SuperHConstantPoolConstant *)MC.Val.MachineCPVal) {
+        if (CPV->getPromotedGlobalInit() == N->getConstantFPValue())
+          return CPV;
+      }
+    }
+  }
+
+  // If not found, create a new one and add it.
+  MachineFunction &MF = DAG.getMachineFunction();
+  SuperHMachineFunctionInfo *SFI = MF.getInfo<SuperHMachineFunctionInfo>();
+  unsigned LabelIndex = SFI->createConstIndex();
+  return SuperHConstantPoolConstant::Create(
+      N->getConstantFPValue(), LabelIndex, SHCP::SHCPKind::CPPromotedGlobal,
+      Modifier);
+}
+
 SuperHConstantPoolSymbol *SuperHMachineFunctionInfo::tryGetConstant(
     ExternalSymbolSDNode *N, SelectionDAG &DAG, SHCP::SHCPModifier Modifier) {
 
diff --git a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
index bc85d83de3d55..bf20e024eb08b 100644
--- a/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHMachineFunctionInfo.h
@@ -66,6 +66,9 @@ class SuperHMachineFunctionInfo : public MachineFunctionInfo {
   SuperHConstantPoolConstant *tryGetConstant(ConstantSDNode *N,
                                              SelectionDAG &DAG,
                                              SHCP::SHCPModifier Modifier);
+  SuperHConstantPoolConstant *tryGetConstant(ConstantFPSDNode *N,
+                                             SelectionDAG &DAG,
+                                             SHCP::SHCPModifier Modifier);
   SuperHConstantPoolSymbol *tryGetConstant(ExternalSymbolSDNode *N,
                                            SelectionDAG &DAG,
                                            SHCP::SHCPModifier Modifier);
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
index 5cc5a7a1709a9..a2857deb26a69 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.cpp
@@ -39,7 +39,7 @@ using namespace llvm;
 SuperHRegisterInfo::SuperHRegisterInfo(const SuperHSubtarget &ST)
     : SuperHGenRegisterInfo(SH::R0, /*DwarfFlavour*/ 0, /*EHFlavor*/ 0,
                             /*PC*/ SH::PC),
-      Subtarget(ST) {}
+      STI(ST) {}
 
 const MCPhysReg *
 SuperHRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
@@ -56,26 +56,6 @@ const uint32_t *SuperHRegisterInfo::getNoPreservedMask() const {
   return CSR_SH_RegMask;
 }
 
-const TargetRegisterClass *
-SuperHRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
-                                              const MachineFunction &MF) const {
-  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
-
-  if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
-    return &SH::GPRRegClass;
-  }
-
-  if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
-    return &SH::GPRRegClass;
-  }
-
-  if (TRI->isTypeLegalForClass(*RC, MVT::i1)) {
-    return &SH::GPRRegClass;
-  }
-
-  return TargetRegisterInfo::getLargestLegalSuperClass(RC, MF);
-}
-
 BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   BitVector Reserved(getNumRegs());
   const SuperHFrameLowering *FR = getFrameLowering(MF);
@@ -90,7 +70,7 @@ BitVector SuperHRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   Reserved.set(SH::R15);
 
   // Reserve GOT pointer
-  if (Subtarget.isPositionIndependent())
+  if (STI.isPositionIndependent())
     Reserved.set(SH::R12);
 
   // Reserver frame pointer if it's used.
@@ -115,12 +95,8 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator 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 TargetFrameLowering *TFI =
-      TM.getSubtargetImpl(MF.getFunction())->getFrameLowering();
-  const TargetInstrInfo &TII =
-      *TM.getSubtargetImpl(MF.getFunction())->getInstrInfo();
+  const TargetFrameLowering *TFI = STI.getFrameLowering();
+  const SuperHInstrInfo *TII = STI.getInstrInfo();
 
   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
   int64_t FrameOffset = MI.getOperand(FIOperandNum+1).getImm();
@@ -134,7 +110,7 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   if (MI.getOpcode() == SH::SHFrmIdx) {
     Register DstReg = MI.getOperand(0).getReg();
     if (DstReg != FrameReg) {
-      TII.copyPhysReg(MBB, MI, DL, DstReg, FrameReg, false, false, false);
+      TII->copyPhysReg(MBB, MI, DL, DstReg, FrameReg, false, false, false);
     }
 
     if (Offset > 0) {
@@ -146,7 +122,7 @@ bool SuperHRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
         int64_t NextOff = Offset % 255;
 
         // Add offset to register.
-        BuildMI(MBB, II, DL, TII.get(SH::ADDI), DstReg)
+        BuildMI(MBB, II, DL, TII->get(SH::ADDI), DstReg)
             .addReg(DstReg, RegState::Kill)
             .addImm(NextOff);
 
diff --git a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
index 9c42adf3298f5..deb621b20e4f7 100644
--- a/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
+++ b/llvm/lib/Target/SuperH/SuperHRegisterInfo.h
@@ -24,19 +24,16 @@ class SuperHSubtarget;
 
 class SuperHRegisterInfo : public SuperHGenRegisterInfo {
 protected:
-  const SuperHSubtarget &Subtarget;
+  const SuperHSubtarget &STI;
 
 public:
-  SuperHRegisterInfo(const SuperHSubtarget &Subtarget);
+  SuperHRegisterInfo(const SuperHSubtarget &STI);
 
   const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
   const uint32_t *getCallPreservedMask(const MachineFunction &MF,
                                        CallingConv::ID CC) const override;
   const uint32_t *getNoPreservedMask() const override;
   BitVector getReservedRegs(const MachineFunction &MF) const override;
-  const TargetRegisterClass *
-  getLargestLegalSuperClass(const TargetRegisterClass *RC,
-                            const MachineFunction &MF) const override;
   Register getFrameRegister(const MachineFunction &MF) const override;
 
   bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
index 20fae60254d58..ee38e183f9576 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.cpp
@@ -28,19 +28,23 @@ using namespace llvm;
 SuperHSubtarget::SuperHSubtarget(const StringRef &CPU, const StringRef &FS,
                                  const TargetMachine &TM)
     : SuperHGenSubtargetInfo(TM.getTargetTriple(), CPU, CPU, FS), TM(TM),
-      InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
-      TSInfo(), FrameLowering(*this) {}
+      InstrInfo(*this), TLInfo(TM, initializeSubtargetDependencies(CPU, FS)),
+      TSInfo(), FrameLowering(*this) {
+
+  // Parse features string.
+  ParseSubtargetFeatures(CPU, CPU, FS);
+
+#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
+  LLVM_DEBUG(dbgs() << #ATTRIBUTE "=" << GETTER() << "\n");
+#include "SuperHGenSubtargetInfo.inc"
+  LLVM_DEBUG(dbgs() << "\n");
+}
 
 SuperHSubtarget::~SuperHSubtarget() = default;
 
-SuperHSubtarget &
+const SuperHSubtarget &
 SuperHSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) {
-  // Determine default and user specified characteristics
-  const Triple &TT = getTargetTriple();
-  std::string CPUName = std::string(CPU);
-
-  // Parse features string.
-  ParseSubtargetFeatures(CPUName, CPUName, FS);
+  ParseSubtargetFeatures(CPU, CPU, FS);
   return *this;
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHSubtarget.h b/llvm/lib/Target/SuperH/SuperHSubtarget.h
index 31f12524a99e6..653a337fb3a8c 100644
--- a/llvm/lib/Target/SuperH/SuperHSubtarget.h
+++ b/llvm/lib/Target/SuperH/SuperHSubtarget.h
@@ -18,7 +18,6 @@
 #include "SuperHISelLowering.h"
 #include "SuperHInstrInfo.h"
 #include "SuperHSelectionDAGInfo.h"
-#include "SuperHTargetMachine.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -109,7 +108,7 @@ class SuperHSubtarget : public SuperHGenSubtargetInfo {
   /// 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 FS);
+  const SuperHSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
index 75542e5efdbb2..4cff91ed1769f 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.cpp
@@ -22,6 +22,7 @@
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/PassRegistry.h"
 #include "llvm/Support/Compiler.h"
+#include <memory>
 #include <optional>
 
 using namespace llvm;
@@ -78,10 +79,34 @@ void SuperHPassConfig::addPreEmitPass2() {
 } // namespace
 
 
+
 //
 //      TARGET MACHINE
 //
 
+/// Processes a CPU name.
+static StringRef getCPU(StringRef CPU, const Triple &TT) {
+#define CASE(ARCH) \
+  case Triple::SuperHSubArch_ ## ARCH: return "sh" # ARCH;
+
+  switch(TT.getSubArch()) {
+  CASE(1);
+  CASE(2);
+  CASE(2a);
+  CASE(2e);
+  CASE(3);
+  CASE(3e);
+  CASE(4);
+  CASE(4a);
+  default:
+    if (CPU.empty() || CPU == "generic") {
+      return "sh4";
+    }
+    return CPU;
+  }
+#undef CASE
+}
+
 SuperHTargetMachine::~SuperHTargetMachine() {}
 
 /// Create a SuperH architecture model.
@@ -94,7 +119,8 @@ SuperHTargetMachine::SuperHTargetMachine(const Target &T, const Triple &TT,
     : CodeGenTargetMachineImpl(T, TT, CPU, FS, Options,
                                RM.value_or(Reloc::Static),
                                getEffectiveCodeModel(CM, CodeModel::Small), OL),
-      TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
+      TLOF(std::make_unique<TargetLoweringObjectFileELF>()),
+      ST(std::make_unique<SuperHSubtarget>(std::string(getCPU(CPU, TT)), std::string(FS), *this)) {
   initAsmInfo();
 }
 
@@ -102,18 +128,13 @@ 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 FSAttr = F.getFnAttribute("target-features");
-
-  std::string CPU =
-      CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
-  std::string FS =
-      FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
+const SuperHSubtarget *
+SuperHTargetMachine::getSubtargetImpl() const {
+  return ST.get();
+}
 
-  if (!ST)
-    ST = std::make_unique<SuperHSubtarget>(CPU, FS, *this);
+const SuperHSubtarget *
+SuperHTargetMachine::getSubtargetImpl(const Function &F) const {
   return ST.get();
 }
 
diff --git a/llvm/lib/Target/SuperH/SuperHTargetMachine.h b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
index 49706933ab773..956148803c9f8 100644
--- a/llvm/lib/Target/SuperH/SuperHTargetMachine.h
+++ b/llvm/lib/Target/SuperH/SuperHTargetMachine.h
@@ -13,10 +13,10 @@
 #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 "SuperHSubtarget.h"
 #include <optional>
 
 namespace llvm {
@@ -37,7 +37,8 @@ class SuperHTargetMachine : public CodeGenTargetMachineImpl {
   createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
                             const TargetSubtargetInfo *STI) const override;
 
-  const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override;
+  const SuperHSubtarget *getSubtargetImpl() const;
+  const SuperHSubtarget *getSubtargetImpl(const Function &) const override;
   TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
   TargetLoweringObjectFile *getObjFileLowering() const override {
     return TLOF.get();



More information about the llvm-commits mailing list