1//===-- MSP430Subtarget.cpp - MSP430 Subtarget Information ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the MSP430 specific subclass of TargetSubtargetInfo.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MSP430Subtarget.h"
14#include "MSP430SelectionDAGInfo.h"
15#include "llvm/MC/TargetRegistry.h"
16
17using namespace llvm;
18
19#define DEBUG_TYPE "msp430-subtarget"
20
21static cl::opt<MSP430Subtarget::HWMultEnum>
22HWMultModeOption("mhwmult", cl::Hidden,
23 cl::desc("Hardware multiplier use mode for MSP430"),
24 cl::init(Val: MSP430Subtarget::NoHWMult),
25 cl::values(
26 clEnumValN(MSP430Subtarget::NoHWMult, "none",
27 "Do not use hardware multiplier"),
28 clEnumValN(MSP430Subtarget::HWMult16, "16bit",
29 "Use 16-bit hardware multiplier"),
30 clEnumValN(MSP430Subtarget::HWMult32, "32bit",
31 "Use 32-bit hardware multiplier"),
32 clEnumValN(MSP430Subtarget::HWMultF5, "f5series",
33 "Use F5 series hardware multiplier")));
34
35#define GET_SUBTARGETINFO_TARGET_DESC
36#define GET_SUBTARGETINFO_CTOR
37#include "MSP430GenSubtargetInfo.inc"
38
39void MSP430Subtarget::anchor() { }
40
41MSP430Subtarget &
42MSP430Subtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) {
43 ExtendedInsts = false;
44 HWMultMode = NoHWMult;
45
46 StringRef CPUName = CPU;
47 if (CPUName.empty())
48 CPUName = "msp430";
49
50 ParseSubtargetFeatures(CPU: CPUName, /*TuneCPU*/ CPUName, FS);
51
52 if (HWMultModeOption != NoHWMult)
53 HWMultMode = HWMultModeOption;
54
55 return *this;
56}
57
58MSP430Subtarget::MSP430Subtarget(const Triple &TT, const std::string &CPU,
59 const std::string &FS, const TargetMachine &TM)
60 : MSP430GenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
61 InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
62 FrameLowering(*this) {
63 TSInfo = std::make_unique<MSP430SelectionDAGInfo>();
64}
65
66MSP430Subtarget::~MSP430Subtarget() = default;
67
68const SelectionDAGTargetInfo *MSP430Subtarget::getSelectionDAGInfo() const {
69 return TSInfo.get();
70}
71
72void MSP430Subtarget::initLibcallLoweringInfo(LibcallLoweringInfo &Info) const {
73 if (hasHWMult16()) {
74 const struct {
75 const RTLIB::Libcall Op;
76 const RTLIB::LibcallImpl Impl;
77 } LibraryCalls[] = {
78 // Integer Multiply - EABI Table 9
79 {.Op: RTLIB::MUL_I16, .Impl: RTLIB::impl___mspabi_mpyi_hw},
80 {.Op: RTLIB::MUL_I32, .Impl: RTLIB::impl___mspabi_mpyl_hw},
81 {.Op: RTLIB::MUL_I64, .Impl: RTLIB::impl___mspabi_mpyll_hw},
82 // TODO The __mspabi_mpysl*_hw functions ARE implemented in libgcc
83 // TODO The __mspabi_mpyul*_hw functions ARE implemented in libgcc
84 };
85 for (const auto &LC : LibraryCalls) {
86 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
87 }
88 } else if (hasHWMult32()) {
89 const struct {
90 const RTLIB::Libcall Op;
91 const RTLIB::LibcallImpl Impl;
92 } LibraryCalls[] = {
93 // Integer Multiply - EABI Table 9
94 {.Op: RTLIB::MUL_I16, .Impl: RTLIB::impl___mspabi_mpyi_hw},
95 {.Op: RTLIB::MUL_I32, .Impl: RTLIB::impl___mspabi_mpyl_hw32},
96 {.Op: RTLIB::MUL_I64, .Impl: RTLIB::impl___mspabi_mpyll_hw32},
97 // TODO The __mspabi_mpysl*_hw32 functions ARE implemented in libgcc
98 // TODO The __mspabi_mpyul*_hw32 functions ARE implemented in libgcc
99 };
100 for (const auto &LC : LibraryCalls) {
101 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
102 }
103 } else if (hasHWMultF5()) {
104 const struct {
105 const RTLIB::Libcall Op;
106 const RTLIB::LibcallImpl Impl;
107 } LibraryCalls[] = {
108 // Integer Multiply - EABI Table 9
109 {.Op: RTLIB::MUL_I16, .Impl: RTLIB::impl___mspabi_mpyi_f5hw},
110 {.Op: RTLIB::MUL_I32, .Impl: RTLIB::impl___mspabi_mpyl_f5hw},
111 {.Op: RTLIB::MUL_I64, .Impl: RTLIB::impl___mspabi_mpyll_f5hw},
112 // TODO The __mspabi_mpysl*_f5hw functions ARE implemented in libgcc
113 // TODO The __mspabi_mpyul*_f5hw functions ARE implemented in libgcc
114 };
115 for (const auto &LC : LibraryCalls) {
116 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
117 }
118 } else { // NoHWMult
119 const struct {
120 const RTLIB::Libcall Op;
121 const RTLIB::LibcallImpl Impl;
122 } LibraryCalls[] = {
123 // Integer Multiply - EABI Table 9
124 {.Op: RTLIB::MUL_I16, .Impl: RTLIB::impl___mspabi_mpyi},
125 {.Op: RTLIB::MUL_I32, .Impl: RTLIB::impl___mspabi_mpyl},
126 {.Op: RTLIB::MUL_I64, .Impl: RTLIB::impl___mspabi_mpyll},
127 // The __mspabi_mpysl* functions are NOT implemented in libgcc
128 // The __mspabi_mpyul* functions are NOT implemented in libgcc
129 };
130 for (const auto &LC : LibraryCalls) {
131 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
132 }
133 }
134
135 // The generic soft-float/integer helper routines (__addsf3, __divli, ...)
136 // exist in msp430 libgcc alongside the __mspabi_* variants, so both are
137 // available. The __mspabi_* variants are the one that should be used.
138 static const struct {
139 const RTLIB::Libcall Op;
140 const RTLIB::LibcallImpl Impl;
141 } EABISelected[] = {
142 // Floating point conversions - EABI Table 6.
143 {.Op: RTLIB::FPROUND_F64_F32, .Impl: RTLIB::impl___mspabi_cvtdf},
144 {.Op: RTLIB::FPEXT_F32_F64, .Impl: RTLIB::impl___mspabi_cvtfd},
145 {.Op: RTLIB::FPTOSINT_F64_I32, .Impl: RTLIB::impl___mspabi_fixdli},
146 {.Op: RTLIB::FPTOSINT_F64_I64, .Impl: RTLIB::impl___mspabi_fixdlli},
147 {.Op: RTLIB::FPTOUINT_F64_I32, .Impl: RTLIB::impl___mspabi_fixdul},
148 {.Op: RTLIB::FPTOUINT_F64_I64, .Impl: RTLIB::impl___mspabi_fixdull},
149 {.Op: RTLIB::FPTOSINT_F32_I32, .Impl: RTLIB::impl___mspabi_fixfli},
150 {.Op: RTLIB::FPTOSINT_F32_I64, .Impl: RTLIB::impl___mspabi_fixflli},
151 {.Op: RTLIB::FPTOUINT_F32_I32, .Impl: RTLIB::impl___mspabi_fixful},
152 {.Op: RTLIB::FPTOUINT_F32_I64, .Impl: RTLIB::impl___mspabi_fixfull},
153 {.Op: RTLIB::SINTTOFP_I32_F64, .Impl: RTLIB::impl___mspabi_fltlid},
154 {.Op: RTLIB::SINTTOFP_I64_F64, .Impl: RTLIB::impl___mspabi_fltllid},
155 {.Op: RTLIB::UINTTOFP_I32_F64, .Impl: RTLIB::impl___mspabi_fltuld},
156 {.Op: RTLIB::UINTTOFP_I64_F64, .Impl: RTLIB::impl___mspabi_fltulld},
157 {.Op: RTLIB::SINTTOFP_I32_F32, .Impl: RTLIB::impl___mspabi_fltlif},
158 {.Op: RTLIB::SINTTOFP_I64_F32, .Impl: RTLIB::impl___mspabi_fltllif},
159 {.Op: RTLIB::UINTTOFP_I32_F32, .Impl: RTLIB::impl___mspabi_fltulf},
160 {.Op: RTLIB::UINTTOFP_I64_F32, .Impl: RTLIB::impl___mspabi_fltullf},
161 // Floating point comparisons - EABI Table 7. A single three-way compare
162 // symbol serves every predicate.
163 {.Op: RTLIB::FCMP3_PRED_OEQ_F64, .Impl: RTLIB::impl___mspabi_cmpd},
164 {.Op: RTLIB::FCMP3_PRED_UNE_F64, .Impl: RTLIB::impl___mspabi_cmpd},
165 {.Op: RTLIB::FCMP3_PRED_OGE_F64, .Impl: RTLIB::impl___mspabi_cmpd},
166 {.Op: RTLIB::FCMP3_PRED_OLT_F64, .Impl: RTLIB::impl___mspabi_cmpd},
167 {.Op: RTLIB::FCMP3_PRED_OLE_F64, .Impl: RTLIB::impl___mspabi_cmpd},
168 {.Op: RTLIB::FCMP3_PRED_OGT_F64, .Impl: RTLIB::impl___mspabi_cmpd},
169 {.Op: RTLIB::FCMP3_PRED_OEQ_F32, .Impl: RTLIB::impl___mspabi_cmpf},
170 {.Op: RTLIB::FCMP3_PRED_UNE_F32, .Impl: RTLIB::impl___mspabi_cmpf},
171 {.Op: RTLIB::FCMP3_PRED_OGE_F32, .Impl: RTLIB::impl___mspabi_cmpf},
172 {.Op: RTLIB::FCMP3_PRED_OLT_F32, .Impl: RTLIB::impl___mspabi_cmpf},
173 {.Op: RTLIB::FCMP3_PRED_OLE_F32, .Impl: RTLIB::impl___mspabi_cmpf},
174 {.Op: RTLIB::FCMP3_PRED_OGT_F32, .Impl: RTLIB::impl___mspabi_cmpf},
175 // Floating point arithmetic - EABI Table 8.
176 {.Op: RTLIB::ADD_F64, .Impl: RTLIB::impl___mspabi_addd},
177 {.Op: RTLIB::SUB_F64, .Impl: RTLIB::impl___mspabi_subd},
178 {.Op: RTLIB::MUL_F64, .Impl: RTLIB::impl___mspabi_mpyd},
179 {.Op: RTLIB::DIV_F64, .Impl: RTLIB::impl___mspabi_divd},
180 {.Op: RTLIB::ADD_F32, .Impl: RTLIB::impl___mspabi_addf},
181 {.Op: RTLIB::SUB_F32, .Impl: RTLIB::impl___mspabi_subf},
182 {.Op: RTLIB::MUL_F32, .Impl: RTLIB::impl___mspabi_mpyf},
183 {.Op: RTLIB::DIV_F32, .Impl: RTLIB::impl___mspabi_divf},
184 // Universal Integer Operations - EABI Table 9.
185 {.Op: RTLIB::SDIV_I16, .Impl: RTLIB::impl___mspabi_divi},
186 {.Op: RTLIB::SDIV_I32, .Impl: RTLIB::impl___mspabi_divli},
187 {.Op: RTLIB::SDIV_I64, .Impl: RTLIB::impl___mspabi_divlli},
188 {.Op: RTLIB::UDIV_I16, .Impl: RTLIB::impl___mspabi_divu},
189 {.Op: RTLIB::UDIV_I32, .Impl: RTLIB::impl___mspabi_divul},
190 {.Op: RTLIB::UDIV_I64, .Impl: RTLIB::impl___mspabi_divull},
191 {.Op: RTLIB::SREM_I16, .Impl: RTLIB::impl___mspabi_remi},
192 {.Op: RTLIB::SREM_I32, .Impl: RTLIB::impl___mspabi_remli},
193 {.Op: RTLIB::SREM_I64, .Impl: RTLIB::impl___mspabi_remlli},
194 {.Op: RTLIB::UREM_I16, .Impl: RTLIB::impl___mspabi_remu},
195 {.Op: RTLIB::UREM_I32, .Impl: RTLIB::impl___mspabi_remul},
196 {.Op: RTLIB::UREM_I64, .Impl: RTLIB::impl___mspabi_remull},
197 // Bitwise Operations - EABI Table 10.
198 {.Op: RTLIB::SHL_I32, .Impl: RTLIB::impl___mspabi_slll},
199 {.Op: RTLIB::SRA_I32, .Impl: RTLIB::impl___mspabi_sral},
200 };
201 for (const auto &LC : EABISelected)
202 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
203}
204