1 //===-- CSKYAsmBackend.cpp - CSKY Assembler Backend -----------------------===// 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 #include "CSKYAsmBackend.h" 10 #include "MCTargetDesc/CSKYMCTargetDesc.h" 11 #include "llvm/ADT/DenseMap.h" 12 #include "llvm/MC/MCAssembler.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/MCFixupKindInfo.h" 15 #include "llvm/MC/MCObjectWriter.h" 16 #include "llvm/Support/Debug.h" 17 18 #define DEBUG_TYPE "csky-asmbackend" 19 20 using namespace llvm; 21 22 std::unique_ptr<MCObjectTargetWriter> 23 CSKYAsmBackend::createObjectTargetWriter() const { 24 return createCSKYELFObjectWriter(); 25 } 26 27 const MCFixupKindInfo & 28 CSKYAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { 29 30 static llvm::DenseMap<unsigned, MCFixupKindInfo> Infos = { 31 {CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}}, 32 {CSKY::Fixups::fixup_csky_addr_hi16, {"fixup_csky_addr_hi16", 0, 32, 0}}, 33 {CSKY::Fixups::fixup_csky_addr_lo16, {"fixup_csky_addr_lo16", 0, 32, 0}}, 34 {CSKY::Fixups::fixup_csky_pcrel_imm16_scale2, 35 {"fixup_csky_pcrel_imm16_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}, 36 {CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4, 37 {"fixup_csky_pcrel_uimm16_scale4", 0, 32, 38 MCFixupKindInfo::FKF_IsPCRel | 39 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}}, 40 {CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4, 41 {"fixup_csky_pcrel_uimm8_scale4", 0, 32, 42 MCFixupKindInfo::FKF_IsPCRel | 43 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}}, 44 {CSKY::Fixups::fixup_csky_pcrel_imm26_scale2, 45 {"fixup_csky_pcrel_imm26_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}, 46 {CSKY::Fixups::fixup_csky_pcrel_imm18_scale2, 47 {"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}, 48 {CSKY::Fixups::fixup_csky_got32, {"fixup_csky_got32", 0, 32, 0}}, 49 {CSKY::Fixups::fixup_csky_got_imm18_scale4, 50 {"fixup_csky_got_imm18_scale4", 0, 32, 0}}, 51 {CSKY::Fixups::fixup_csky_gotoff, {"fixup_csky_gotoff", 0, 32, 0}}, 52 {CSKY::Fixups::fixup_csky_gotpc, 53 {"fixup_csky_gotpc", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}, 54 {CSKY::Fixups::fixup_csky_plt32, {"fixup_csky_plt32", 0, 32, 0}}, 55 {CSKY::Fixups::fixup_csky_plt_imm18_scale4, 56 {"fixup_csky_plt_imm18_scale4", 0, 32, 0}}, 57 {CSKY::Fixups::fixup_csky_pcrel_imm10_scale2, 58 {"fixup_csky_pcrel_imm10_scale2", 0, 16, MCFixupKindInfo::FKF_IsPCRel}}, 59 {CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4, 60 {"fixup_csky_pcrel_uimm7_scale4", 0, 16, 61 MCFixupKindInfo::FKF_IsPCRel | 62 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}}, 63 {CSKY::Fixups::fixup_csky_doffset_imm18, 64 {"fixup_csky_doffset_imm18", 0, 18, 0}}, 65 {CSKY::Fixups::fixup_csky_doffset_imm18_scale2, 66 {"fixup_csky_doffset_imm18_scale2", 0, 18, 0}}, 67 {CSKY::Fixups::fixup_csky_doffset_imm18_scale4, 68 {"fixup_csky_doffset_imm18_scale4", 0, 18, 0}}}; 69 70 assert(Infos.size() == CSKY::NumTargetFixupKinds && 71 "Not all fixup kinds added to Infos array"); 72 73 if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind) { 74 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 75 "Invalid kind!"); 76 77 return Infos[Kind]; 78 } else if (Kind < FirstTargetFixupKind) { 79 return MCAsmBackend::getFixupKindInfo(Kind); 80 } else { 81 return MCAsmBackend::getFixupKindInfo(FK_NONE); 82 } 83 } 84 85 static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, 86 MCContext &Ctx) { 87 switch (Fixup.getTargetKind()) { 88 default: 89 llvm_unreachable("Unknown fixup kind!"); 90 case CSKY::fixup_csky_got32: 91 case CSKY::fixup_csky_got_imm18_scale4: 92 case CSKY::fixup_csky_gotoff: 93 case CSKY::fixup_csky_gotpc: 94 case CSKY::fixup_csky_plt32: 95 case CSKY::fixup_csky_plt_imm18_scale4: 96 llvm_unreachable("Relocation should be unconditionally forced\n"); 97 case FK_Data_1: 98 case FK_Data_2: 99 case FK_Data_4: 100 case FK_Data_8: 101 return Value; 102 case CSKY::fixup_csky_addr32: 103 return Value & 0xffffffff; 104 case CSKY::fixup_csky_pcrel_imm16_scale2: 105 if (!isIntN(17, Value)) 106 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); 107 if (Value & 0x1) 108 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned."); 109 110 return (Value >> 1) & 0xffff; 111 case CSKY::fixup_csky_pcrel_uimm16_scale4: 112 if (!isUIntN(18, Value)) 113 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); 114 if (Value & 0x3) 115 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned."); 116 117 return (Value >> 2) & 0xffff; 118 case CSKY::fixup_csky_pcrel_imm26_scale2: 119 if (!isIntN(27, Value)) 120 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); 121 if (Value & 0x1) 122 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned."); 123 124 return (Value >> 1) & 0x3ffffff; 125 case CSKY::fixup_csky_pcrel_imm18_scale2: 126 if (!isIntN(19, Value)) 127 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); 128 if (Value & 0x1) 129 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned."); 130 131 return (Value >> 1) & 0x3ffff; 132 case CSKY::fixup_csky_pcrel_uimm8_scale4: { 133 if (!isUIntN(10, Value)) 134 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); 135 if (Value & 0x3) 136 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned."); 137 138 unsigned IMM4L = (Value >> 2) & 0xf; 139 unsigned IMM4H = (Value >> 6) & 0xf; 140 141 Value = (IMM4H << 21) | (IMM4L << 4); 142 return Value; 143 } 144 case CSKY::fixup_csky_pcrel_imm10_scale2: 145 if (!isIntN(11, Value)) 146 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); 147 if (Value & 0x1) 148 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned."); 149 150 return (Value >> 1) & 0x3ff; 151 case CSKY::fixup_csky_pcrel_uimm7_scale4: 152 if ((Value >> 2) > 0xfe) 153 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value."); 154 if (Value & 0x3) 155 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned."); 156 157 if ((Value >> 2) <= 0x7f) { 158 unsigned IMM5L = (Value >> 2) & 0x1f; 159 unsigned IMM2H = (Value >> 7) & 0x3; 160 161 Value = (1 << 12) | (IMM2H << 8) | IMM5L; 162 } else { 163 unsigned IMM5L = (~Value >> 2) & 0x1f; 164 unsigned IMM2H = (~Value >> 7) & 0x3; 165 166 Value = (IMM2H << 8) | IMM5L; 167 } 168 169 return Value; 170 } 171 } 172 173 bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCAssembler &Asm, 174 const MCFixup &Fixup, 175 bool Resolved, uint64_t Value, 176 const MCRelaxableFragment *DF, 177 const bool WasForced) const { 178 // Return true if the symbol is actually unresolved. 179 // Resolved could be always false when shouldForceRelocation return true. 180 // We use !WasForced to indicate that the symbol is unresolved and not forced 181 // by shouldForceRelocation. 182 if (!Resolved && !WasForced) 183 return true; 184 185 int64_t Offset = int64_t(Value); 186 switch (Fixup.getTargetKind()) { 187 default: 188 return false; 189 case CSKY::fixup_csky_pcrel_imm10_scale2: 190 return !isShiftedInt<10, 1>(Offset); 191 case CSKY::fixup_csky_pcrel_imm16_scale2: 192 return !isShiftedInt<16, 1>(Offset); 193 case CSKY::fixup_csky_pcrel_imm26_scale2: 194 return !isShiftedInt<26, 1>(Offset); 195 case CSKY::fixup_csky_pcrel_uimm7_scale4: 196 return ((Value >> 2) > 0xfe) || (Value & 0x3); 197 } 198 } 199 200 void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 201 const MCValue &Target, 202 MutableArrayRef<char> Data, uint64_t Value, 203 bool IsResolved, 204 const MCSubtargetInfo *STI) const { 205 MCFixupKind Kind = Fixup.getKind(); 206 if (Kind >= FirstLiteralRelocationKind) 207 return; 208 MCContext &Ctx = Asm.getContext(); 209 MCFixupKindInfo Info = getFixupKindInfo(Kind); 210 if (!Value) 211 return; // Doesn't change encoding. 212 // Apply any target-specific value adjustments. 213 Value = adjustFixupValue(Fixup, Value, Ctx); 214 215 // Shift the value into position. 216 Value <<= Info.TargetOffset; 217 218 unsigned Offset = Fixup.getOffset(); 219 unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8; 220 221 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); 222 223 // For each byte of the fragment that the fixup touches, mask in the 224 // bits from the fixup value. 225 bool IsLittleEndian = (Endian == llvm::endianness::little); 226 bool IsInstFixup = (Kind >= FirstTargetFixupKind); 227 228 if (IsLittleEndian && IsInstFixup && (NumBytes == 4)) { 229 Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff); 230 Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff); 231 Data[Offset + 2] |= uint8_t(Value & 0xff); 232 Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff); 233 } else { 234 for (unsigned I = 0; I != NumBytes; I++) { 235 unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I); 236 Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff); 237 } 238 } 239 } 240 241 bool CSKYAsmBackend::mayNeedRelaxation(const MCInst &Inst, 242 const MCSubtargetInfo &STI) const { 243 switch (Inst.getOpcode()) { 244 default: 245 return false; 246 case CSKY::JBR32: 247 case CSKY::JBT32: 248 case CSKY::JBF32: 249 case CSKY::JBSR32: 250 if (!STI.hasFeature(CSKY::Has2E3)) 251 return false; 252 return true; 253 case CSKY::JBR16: 254 case CSKY::JBT16: 255 case CSKY::JBF16: 256 case CSKY::LRW16: 257 case CSKY::BR16: 258 return true; 259 } 260 } 261 262 bool CSKYAsmBackend::shouldForceRelocation(const MCAssembler &Asm, 263 const MCFixup &Fixup, 264 const MCValue &Target, 265 const MCSubtargetInfo * /*STI*/) { 266 if (Fixup.getKind() >= FirstLiteralRelocationKind) 267 return true; 268 switch (Fixup.getTargetKind()) { 269 default: 270 break; 271 case CSKY::fixup_csky_got32: 272 case CSKY::fixup_csky_got_imm18_scale4: 273 case CSKY::fixup_csky_gotoff: 274 case CSKY::fixup_csky_gotpc: 275 case CSKY::fixup_csky_plt32: 276 case CSKY::fixup_csky_plt_imm18_scale4: 277 case CSKY::fixup_csky_doffset_imm18: 278 case CSKY::fixup_csky_doffset_imm18_scale2: 279 case CSKY::fixup_csky_doffset_imm18_scale4: 280 return true; 281 } 282 283 return false; 284 } 285 286 bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 287 uint64_t Value) const { 288 return false; 289 } 290 291 void CSKYAsmBackend::relaxInstruction(MCInst &Inst, 292 const MCSubtargetInfo &STI) const { 293 MCInst Res; 294 295 switch (Inst.getOpcode()) { 296 default: 297 LLVM_DEBUG(Inst.dump()); 298 llvm_unreachable("Opcode not expected!"); 299 case CSKY::LRW16: 300 Res.setOpcode(CSKY::LRW32); 301 Res.addOperand(Inst.getOperand(0)); 302 Res.addOperand(Inst.getOperand(1)); 303 break; 304 case CSKY::BR16: 305 Res.setOpcode(CSKY::BR32); 306 Res.addOperand(Inst.getOperand(0)); 307 break; 308 case CSKY::JBSR32: 309 Res.setOpcode(CSKY::JSRI32); 310 Res.addOperand(Inst.getOperand(1)); 311 break; 312 case CSKY::JBR32: 313 Res.setOpcode(CSKY::JMPI32); 314 Res.addOperand(Inst.getOperand(1)); 315 break; 316 case CSKY::JBT32: 317 case CSKY::JBF32: 318 Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E); 319 Res.addOperand(Inst.getOperand(0)); 320 Res.addOperand(Inst.getOperand(1)); 321 Res.addOperand(Inst.getOperand(2)); 322 break; 323 case CSKY::JBR16: 324 Res.setOpcode(CSKY::JBR32); 325 Res.addOperand(Inst.getOperand(0)); 326 Res.addOperand(Inst.getOperand(1)); 327 break; 328 case CSKY::JBT16: 329 case CSKY::JBF16: 330 // ck801 331 unsigned opcode; 332 if (STI.hasFeature(CSKY::HasE2)) 333 opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32; 334 else 335 opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E; 336 337 Res.setOpcode(opcode); 338 Res.addOperand(Inst.getOperand(0)); 339 Res.addOperand(Inst.getOperand(1)); 340 Res.addOperand(Inst.getOperand(2)); 341 break; 342 } 343 Inst = std::move(Res); 344 } 345 346 bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, 347 const MCSubtargetInfo *STI) const { 348 OS.write_zeros(Count); 349 return true; 350 } 351 352 MCAsmBackend *llvm::createCSKYAsmBackend(const Target &T, 353 const MCSubtargetInfo &STI, 354 const MCRegisterInfo &MRI, 355 const MCTargetOptions &Options) { 356 return new CSKYAsmBackend(STI, Options); 357 } 358