1 //===-- RISCVAsmBackend.cpp - RISCV Assembler Backend ---------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "RISCVAsmBackend.h" 11 #include "llvm/ADT/APInt.h" 12 #include "llvm/MC/MCAssembler.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/MCDirectives.h" 15 #include "llvm/MC/MCELFObjectWriter.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCObjectWriter.h" 18 #include "llvm/MC/MCSymbol.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 using namespace llvm; 23 24 bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, 25 bool Resolved, 26 uint64_t Value, 27 const MCRelaxableFragment *DF, 28 const MCAsmLayout &Layout, 29 const bool WasForced) const { 30 // Return true if the symbol is actually unresolved. 31 // Resolved could be always false when shouldForceRelocation return true. 32 // We use !WasForced to indicate that the symbol is unresolved and not forced 33 // by shouldForceRelocation. 34 if (!Resolved && !WasForced) 35 return true; 36 37 int64_t Offset = int64_t(Value); 38 switch ((unsigned)Fixup.getKind()) { 39 default: 40 return false; 41 case RISCV::fixup_riscv_rvc_branch: 42 // For compressed branch instructions the immediate must be 43 // in the range [-256, 254]. 44 return Offset > 254 || Offset < -256; 45 case RISCV::fixup_riscv_rvc_jump: 46 // For compressed jump instructions the immediate must be 47 // in the range [-2048, 2046]. 48 return Offset > 2046 || Offset < -2048; 49 } 50 } 51 52 void RISCVAsmBackend::relaxInstruction(const MCInst &Inst, 53 const MCSubtargetInfo &STI, 54 MCInst &Res) const { 55 // TODO: replace this with call to auto generated uncompressinstr() function. 56 switch (Inst.getOpcode()) { 57 default: 58 llvm_unreachable("Opcode not expected!"); 59 case RISCV::C_BEQZ: 60 // c.beqz $rs1, $imm -> beq $rs1, X0, $imm. 61 Res.setOpcode(RISCV::BEQ); 62 Res.addOperand(Inst.getOperand(0)); 63 Res.addOperand(MCOperand::createReg(RISCV::X0)); 64 Res.addOperand(Inst.getOperand(1)); 65 break; 66 case RISCV::C_BNEZ: 67 // c.bnez $rs1, $imm -> bne $rs1, X0, $imm. 68 Res.setOpcode(RISCV::BNE); 69 Res.addOperand(Inst.getOperand(0)); 70 Res.addOperand(MCOperand::createReg(RISCV::X0)); 71 Res.addOperand(Inst.getOperand(1)); 72 break; 73 case RISCV::C_J: 74 // c.j $imm -> jal X0, $imm. 75 Res.setOpcode(RISCV::JAL); 76 Res.addOperand(MCOperand::createReg(RISCV::X0)); 77 Res.addOperand(Inst.getOperand(0)); 78 break; 79 case RISCV::C_JAL: 80 // c.jal $imm -> jal X1, $imm. 81 Res.setOpcode(RISCV::JAL); 82 Res.addOperand(MCOperand::createReg(RISCV::X1)); 83 Res.addOperand(Inst.getOperand(0)); 84 break; 85 } 86 } 87 88 // Given a compressed control flow instruction this function returns 89 // the expanded instruction. 90 unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const { 91 switch (Op) { 92 default: 93 return Op; 94 case RISCV::C_BEQZ: 95 return RISCV::BEQ; 96 case RISCV::C_BNEZ: 97 return RISCV::BNE; 98 case RISCV::C_J: 99 case RISCV::C_JAL: // fall through. 100 return RISCV::JAL; 101 } 102 } 103 104 bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst, 105 const MCSubtargetInfo &STI) const { 106 return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode(); 107 } 108 109 bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { 110 bool HasStdExtC = STI.getFeatureBits()[RISCV::FeatureStdExtC]; 111 unsigned MinNopLen = HasStdExtC ? 2 : 4; 112 113 if ((Count % MinNopLen) != 0) 114 return false; 115 116 // The canonical nop on RISC-V is addi x0, x0, 0. 117 uint64_t Nop32Count = Count / 4; 118 for (uint64_t i = Nop32Count; i != 0; --i) 119 OS.write("\x13\0\0\0", 4); 120 121 // The canonical nop on RVC is c.nop. 122 if (HasStdExtC) { 123 uint64_t Nop16Count = (Count - Nop32Count * 4) / 2; 124 for (uint64_t i = Nop16Count; i != 0; --i) 125 OS.write("\x01\0", 2); 126 } 127 128 return true; 129 } 130 131 static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, 132 MCContext &Ctx) { 133 unsigned Kind = Fixup.getKind(); 134 switch (Kind) { 135 default: 136 llvm_unreachable("Unknown fixup kind!"); 137 case FK_Data_1: 138 case FK_Data_2: 139 case FK_Data_4: 140 case FK_Data_8: 141 return Value; 142 case RISCV::fixup_riscv_lo12_i: 143 case RISCV::fixup_riscv_pcrel_lo12_i: 144 return Value & 0xfff; 145 case RISCV::fixup_riscv_lo12_s: 146 case RISCV::fixup_riscv_pcrel_lo12_s: 147 return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7); 148 case RISCV::fixup_riscv_hi20: 149 case RISCV::fixup_riscv_pcrel_hi20: 150 // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative. 151 return ((Value + 0x800) >> 12) & 0xfffff; 152 case RISCV::fixup_riscv_jal: { 153 if (!isInt<21>(Value)) 154 Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); 155 if (Value & 0x1) 156 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned"); 157 // Need to produce imm[19|10:1|11|19:12] from the 21-bit Value. 158 unsigned Sbit = (Value >> 20) & 0x1; 159 unsigned Hi8 = (Value >> 12) & 0xff; 160 unsigned Mid1 = (Value >> 11) & 0x1; 161 unsigned Lo10 = (Value >> 1) & 0x3ff; 162 // Inst{31} = Sbit; 163 // Inst{30-21} = Lo10; 164 // Inst{20} = Mid1; 165 // Inst{19-12} = Hi8; 166 Value = (Sbit << 19) | (Lo10 << 9) | (Mid1 << 8) | Hi8; 167 return Value; 168 } 169 case RISCV::fixup_riscv_branch: { 170 if (!isInt<13>(Value)) 171 Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); 172 if (Value & 0x1) 173 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned"); 174 // Need to extract imm[12], imm[10:5], imm[4:1], imm[11] from the 13-bit 175 // Value. 176 unsigned Sbit = (Value >> 12) & 0x1; 177 unsigned Hi1 = (Value >> 11) & 0x1; 178 unsigned Mid6 = (Value >> 5) & 0x3f; 179 unsigned Lo4 = (Value >> 1) & 0xf; 180 // Inst{31} = Sbit; 181 // Inst{30-25} = Mid6; 182 // Inst{11-8} = Lo4; 183 // Inst{7} = Hi1; 184 Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7); 185 return Value; 186 } 187 case RISCV::fixup_riscv_call: { 188 // Jalr will add UpperImm with the sign-extended 12-bit LowerImm, 189 // we need to add 0x800ULL before extract upper bits to reflect the 190 // effect of the sign extension. 191 uint64_t UpperImm = (Value + 0x800ULL) & 0xfffff000ULL; 192 uint64_t LowerImm = Value & 0xfffULL; 193 return UpperImm | ((LowerImm << 20) << 32); 194 } 195 case RISCV::fixup_riscv_rvc_jump: { 196 // Need to produce offset[11|4|9:8|10|6|7|3:1|5] from the 11-bit Value. 197 unsigned Bit11 = (Value >> 11) & 0x1; 198 unsigned Bit4 = (Value >> 4) & 0x1; 199 unsigned Bit9_8 = (Value >> 8) & 0x3; 200 unsigned Bit10 = (Value >> 10) & 0x1; 201 unsigned Bit6 = (Value >> 6) & 0x1; 202 unsigned Bit7 = (Value >> 7) & 0x1; 203 unsigned Bit3_1 = (Value >> 1) & 0x7; 204 unsigned Bit5 = (Value >> 5) & 0x1; 205 Value = (Bit11 << 10) | (Bit4 << 9) | (Bit9_8 << 7) | (Bit10 << 6) | 206 (Bit6 << 5) | (Bit7 << 4) | (Bit3_1 << 1) | Bit5; 207 return Value; 208 } 209 case RISCV::fixup_riscv_rvc_branch: { 210 // Need to produce offset[8|4:3], [reg 3 bit], offset[7:6|2:1|5] 211 unsigned Bit8 = (Value >> 8) & 0x1; 212 unsigned Bit7_6 = (Value >> 6) & 0x3; 213 unsigned Bit5 = (Value >> 5) & 0x1; 214 unsigned Bit4_3 = (Value >> 3) & 0x3; 215 unsigned Bit2_1 = (Value >> 1) & 0x3; 216 Value = (Bit8 << 12) | (Bit4_3 << 10) | (Bit7_6 << 5) | (Bit2_1 << 3) | 217 (Bit5 << 2); 218 return Value; 219 } 220 221 } 222 } 223 224 void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 225 const MCValue &Target, 226 MutableArrayRef<char> Data, uint64_t Value, 227 bool IsResolved, 228 const MCSubtargetInfo *STI) const { 229 MCContext &Ctx = Asm.getContext(); 230 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); 231 if (!Value) 232 return; // Doesn't change encoding. 233 // Apply any target-specific value adjustments. 234 Value = adjustFixupValue(Fixup, Value, Ctx); 235 236 // Shift the value into position. 237 Value <<= Info.TargetOffset; 238 239 unsigned Offset = Fixup.getOffset(); 240 unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8; 241 242 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); 243 244 // For each byte of the fragment that the fixup touches, mask in the 245 // bits from the fixup value. 246 for (unsigned i = 0; i != NumBytes; ++i) { 247 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 248 } 249 } 250 251 std::unique_ptr<MCObjectTargetWriter> 252 RISCVAsmBackend::createObjectTargetWriter() const { 253 return createRISCVELFObjectWriter(OSABI, Is64Bit); 254 } 255 256 MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T, 257 const MCSubtargetInfo &STI, 258 const MCRegisterInfo &MRI, 259 const MCTargetOptions &Options) { 260 const Triple &TT = STI.getTargetTriple(); 261 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); 262 return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit()); 263 } 264