1 //===-- AVRMCCodeEmitter.cpp - Convert AVR Code to Machine Code -----------===// 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 AVRMCCodeEmitter class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "AVRMCCodeEmitter.h" 14 15 #include "MCTargetDesc/AVRMCExpr.h" 16 #include "MCTargetDesc/AVRMCTargetDesc.h" 17 18 #include "llvm/ADT/APFloat.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/MC/MCContext.h" 21 #include "llvm/MC/MCExpr.h" 22 #include "llvm/MC/MCFixup.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/MC/MCInstrInfo.h" 25 #include "llvm/MC/MCRegisterInfo.h" 26 #include "llvm/MC/MCSubtargetInfo.h" 27 #include "llvm/Support/Casting.h" 28 #include "llvm/Support/EndianStream.h" 29 #include "llvm/Support/raw_ostream.h" 30 31 #define DEBUG_TYPE "mccodeemitter" 32 33 #define GET_INSTRMAP_INFO 34 #include "AVRGenInstrInfo.inc" 35 #undef GET_INSTRMAP_INFO 36 37 namespace llvm { 38 39 /// Performs a post-encoding step on a `LD` or `ST` instruction. 40 /// 41 /// The encoding of the LD/ST family of instructions is inconsistent w.r.t 42 /// the pointer register and the addressing mode. 43 /// 44 /// The permutations of the format are as followed: 45 /// ld Rd, X `1001 000d dddd 1100` 46 /// ld Rd, X+ `1001 000d dddd 1101` 47 /// ld Rd, -X `1001 000d dddd 1110` 48 /// 49 /// ld Rd, Y `1000 000d dddd 1000` 50 /// ld Rd, Y+ `1001 000d dddd 1001` 51 /// ld Rd, -Y `1001 000d dddd 1010` 52 /// 53 /// ld Rd, Z `1000 000d dddd 0000` 54 /// ld Rd, Z+ `1001 000d dddd 0001` 55 /// ld Rd, -Z `1001 000d dddd 0010` 56 /// ^ 57 /// | 58 /// Note this one inconsistent bit - it is 1 sometimes and 0 at other times. 59 /// There is no logical pattern. Looking at a truth table, the following 60 /// formula can be derived to fit the pattern: 61 // 62 /// ``` 63 /// inconsistent_bit = is_predec OR is_postinc OR is_reg_x 64 /// ``` 65 // 66 /// We manually set this bit in this post encoder method. 67 unsigned 68 AVRMCCodeEmitter::loadStorePostEncoder(const MCInst &MI, unsigned EncodedValue, 69 const MCSubtargetInfo &STI) const { 70 71 assert(MI.getOperand(0).isReg() && MI.getOperand(1).isReg() && 72 "the load/store operands must be registers"); 73 74 unsigned Opcode = MI.getOpcode(); 75 76 // check whether either of the registers are the X pointer register. 77 bool IsRegX = MI.getOperand(0).getReg() == AVR::R27R26 || 78 MI.getOperand(1).getReg() == AVR::R27R26; 79 80 bool IsPredec = Opcode == AVR::LDRdPtrPd || Opcode == AVR::STPtrPdRr; 81 bool IsPostinc = Opcode == AVR::LDRdPtrPi || Opcode == AVR::STPtrPiRr; 82 83 // Check if we need to set the inconsistent bit 84 if (IsRegX || IsPredec || IsPostinc) { 85 EncodedValue |= (1 << 12); 86 } 87 88 return EncodedValue; 89 } 90 91 template <AVR::Fixups Fixup> 92 unsigned 93 AVRMCCodeEmitter::encodeRelCondBrTarget(const MCInst &MI, unsigned OpNo, 94 SmallVectorImpl<MCFixup> &Fixups, 95 const MCSubtargetInfo &STI) const { 96 const MCOperand &MO = MI.getOperand(OpNo); 97 98 if (MO.isExpr()) { 99 Fixups.push_back(MCFixup::create(0, MO.getExpr(), 100 MCFixupKind(Fixup), MI.getLoc())); 101 return 0; 102 } 103 104 assert(MO.isImm()); 105 106 // Take the size of the current instruction away. 107 // With labels, this is implicitly done. 108 auto target = MO.getImm(); 109 AVR::fixups::adjustBranchTarget(target); 110 return target; 111 } 112 113 unsigned AVRMCCodeEmitter::encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo, 114 SmallVectorImpl<MCFixup> &Fixups, 115 const MCSubtargetInfo &STI) const { 116 auto MO = MI.getOperand(OpNo); 117 118 // The operand should be a pointer register. 119 assert(MO.isReg()); 120 121 switch (MO.getReg()) { 122 case AVR::R27R26: return 0x03; // X: 0b11 123 case AVR::R29R28: return 0x02; // Y: 0b10 124 case AVR::R31R30: return 0x00; // Z: 0b00 125 default: 126 llvm_unreachable("invalid pointer register"); 127 } 128 } 129 130 /// Encodes a `memri` operand. 131 /// The operand is 7-bits. 132 /// * The lower 6 bits is the immediate 133 /// * The upper bit is the pointer register bit (Z=0,Y=1) 134 unsigned AVRMCCodeEmitter::encodeMemri(const MCInst &MI, unsigned OpNo, 135 SmallVectorImpl<MCFixup> &Fixups, 136 const MCSubtargetInfo &STI) const { 137 auto RegOp = MI.getOperand(OpNo); 138 auto OffsetOp = MI.getOperand(OpNo + 1); 139 140 assert(RegOp.isReg() && "Expected register operand"); 141 142 uint8_t RegBit = 0; 143 144 switch (RegOp.getReg()) { 145 default: 146 llvm_unreachable("Expected either Y or Z register"); 147 case AVR::R31R30: 148 RegBit = 0; 149 break; // Z register 150 case AVR::R29R28: 151 RegBit = 1; 152 break; // Y register 153 } 154 155 int8_t OffsetBits; 156 157 if (OffsetOp.isImm()) { 158 OffsetBits = OffsetOp.getImm(); 159 } else if (OffsetOp.isExpr()) { 160 OffsetBits = 0; 161 Fixups.push_back(MCFixup::create(0, OffsetOp.getExpr(), 162 MCFixupKind(AVR::fixup_6), MI.getLoc())); 163 } else { 164 llvm_unreachable("invalid value for offset"); 165 } 166 167 return (RegBit << 6) | OffsetBits; 168 } 169 170 unsigned AVRMCCodeEmitter::encodeComplement(const MCInst &MI, unsigned OpNo, 171 SmallVectorImpl<MCFixup> &Fixups, 172 const MCSubtargetInfo &STI) const { 173 // The operand should be an immediate. 174 assert(MI.getOperand(OpNo).isImm()); 175 176 auto Imm = MI.getOperand(OpNo).getImm(); 177 return (~0) - Imm; 178 } 179 180 template <AVR::Fixups Fixup, unsigned Offset> 181 unsigned AVRMCCodeEmitter::encodeImm(const MCInst &MI, unsigned OpNo, 182 SmallVectorImpl<MCFixup> &Fixups, 183 const MCSubtargetInfo &STI) const { 184 auto MO = MI.getOperand(OpNo); 185 186 if (MO.isExpr()) { 187 if (isa<AVRMCExpr>(MO.getExpr())) { 188 // If the expression is already an AVRMCExpr (i.e. a lo8(symbol), 189 // we shouldn't perform any more fixups. Without this check, we would 190 // instead create a fixup to the symbol named 'lo8(symbol)' which 191 // is not correct. 192 return getExprOpValue(MO.getExpr(), Fixups, STI); 193 } 194 195 MCFixupKind FixupKind = static_cast<MCFixupKind>(Fixup); 196 Fixups.push_back(MCFixup::create(Offset, MO.getExpr(), FixupKind, MI.getLoc())); 197 198 return 0; 199 } 200 201 assert(MO.isImm()); 202 return MO.getImm(); 203 } 204 205 unsigned AVRMCCodeEmitter::encodeCallTarget(const MCInst &MI, unsigned OpNo, 206 SmallVectorImpl<MCFixup> &Fixups, 207 const MCSubtargetInfo &STI) const { 208 auto MO = MI.getOperand(OpNo); 209 210 if (MO.isExpr()) { 211 MCFixupKind FixupKind = static_cast<MCFixupKind>(AVR::fixup_call); 212 Fixups.push_back(MCFixup::create(0, MO.getExpr(), FixupKind, MI.getLoc())); 213 return 0; 214 } 215 216 assert(MO.isImm()); 217 218 auto Target = MO.getImm(); 219 AVR::fixups::adjustBranchTarget(Target); 220 return Target; 221 } 222 223 unsigned AVRMCCodeEmitter::getExprOpValue(const MCExpr *Expr, 224 SmallVectorImpl<MCFixup> &Fixups, 225 const MCSubtargetInfo &STI) const { 226 227 MCExpr::ExprKind Kind = Expr->getKind(); 228 229 if (Kind == MCExpr::Binary) { 230 Expr = static_cast<const MCBinaryExpr *>(Expr)->getLHS(); 231 Kind = Expr->getKind(); 232 } 233 234 if (Kind == MCExpr::Target) { 235 AVRMCExpr const *AVRExpr = cast<AVRMCExpr>(Expr); 236 int64_t Result; 237 if (AVRExpr->evaluateAsConstant(Result)) { 238 return Result; 239 } 240 241 MCFixupKind FixupKind = static_cast<MCFixupKind>(AVRExpr->getFixupKind()); 242 Fixups.push_back(MCFixup::create(0, AVRExpr, FixupKind)); 243 return 0; 244 } 245 246 assert(Kind == MCExpr::SymbolRef); 247 return 0; 248 } 249 250 unsigned AVRMCCodeEmitter::getMachineOpValue(const MCInst &MI, 251 const MCOperand &MO, 252 SmallVectorImpl<MCFixup> &Fixups, 253 const MCSubtargetInfo &STI) const { 254 if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 255 if (MO.isImm()) return static_cast<unsigned>(MO.getImm()); 256 257 if (MO.isDFPImm()) 258 return static_cast<unsigned>(bit_cast<double>(MO.getDFPImm())); 259 260 // MO must be an Expr. 261 assert(MO.isExpr()); 262 263 return getExprOpValue(MO.getExpr(), Fixups, STI); 264 } 265 266 void AVRMCCodeEmitter::emitInstruction(uint64_t Val, unsigned Size, 267 const MCSubtargetInfo &STI, 268 raw_ostream &OS) const { 269 size_t WordCount = Size / 2; 270 271 for (int64_t i = WordCount - 1; i >= 0; --i) { 272 uint16_t Word = (Val >> (i * 16)) & 0xFFFF; 273 support::endian::write(OS, Word, support::endianness::little); 274 } 275 } 276 277 void AVRMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 278 SmallVectorImpl<MCFixup> &Fixups, 279 const MCSubtargetInfo &STI) const { 280 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 281 282 // Get byte count of instruction 283 unsigned Size = Desc.getSize(); 284 285 assert(Size > 0 && "Instruction size cannot be zero"); 286 287 uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI); 288 emitInstruction(BinaryOpCode, Size, STI, OS); 289 } 290 291 MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII, 292 const MCRegisterInfo &MRI, 293 MCContext &Ctx) { 294 return new AVRMCCodeEmitter(MCII, Ctx); 295 } 296 297 #include "AVRGenMCCodeEmitter.inc" 298 299 } // end of namespace llvm 300