xref: /openbsd-src/gnu/llvm/llvm/lib/Target/AVR/MCTargetDesc/AVRMCCodeEmitter.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- AVRMCCodeEmitter.cpp - Convert AVR Code to Machine Code -----------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements the AVRMCCodeEmitter class.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "AVRMCCodeEmitter.h"
1409467b48Spatrick 
1509467b48Spatrick #include "MCTargetDesc/AVRMCExpr.h"
1609467b48Spatrick #include "MCTargetDesc/AVRMCTargetDesc.h"
1709467b48Spatrick 
1809467b48Spatrick #include "llvm/ADT/APFloat.h"
1909467b48Spatrick #include "llvm/ADT/SmallVector.h"
2009467b48Spatrick #include "llvm/MC/MCContext.h"
2109467b48Spatrick #include "llvm/MC/MCExpr.h"
2209467b48Spatrick #include "llvm/MC/MCFixup.h"
2309467b48Spatrick #include "llvm/MC/MCInst.h"
2409467b48Spatrick #include "llvm/MC/MCInstrInfo.h"
2509467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
2609467b48Spatrick #include "llvm/MC/MCSubtargetInfo.h"
2709467b48Spatrick #include "llvm/Support/Casting.h"
2809467b48Spatrick #include "llvm/Support/EndianStream.h"
2909467b48Spatrick #include "llvm/Support/raw_ostream.h"
3009467b48Spatrick 
3109467b48Spatrick #define DEBUG_TYPE "mccodeemitter"
3209467b48Spatrick 
3309467b48Spatrick #define GET_INSTRMAP_INFO
3409467b48Spatrick #include "AVRGenInstrInfo.inc"
3509467b48Spatrick #undef GET_INSTRMAP_INFO
3609467b48Spatrick 
3709467b48Spatrick namespace llvm {
3809467b48Spatrick 
3909467b48Spatrick /// Performs a post-encoding step on a `LD` or `ST` instruction.
4009467b48Spatrick ///
4109467b48Spatrick /// The encoding of the LD/ST family of instructions is inconsistent w.r.t
4209467b48Spatrick /// the pointer register and the addressing mode.
4309467b48Spatrick ///
4409467b48Spatrick /// The permutations of the format are as followed:
4509467b48Spatrick /// ld Rd, X    `1001 000d dddd 1100`
4609467b48Spatrick /// ld Rd, X+   `1001 000d dddd 1101`
4709467b48Spatrick /// ld Rd, -X   `1001 000d dddd 1110`
4809467b48Spatrick ///
4909467b48Spatrick /// ld Rd, Y    `1000 000d dddd 1000`
5009467b48Spatrick /// ld Rd, Y+   `1001 000d dddd 1001`
5109467b48Spatrick /// ld Rd, -Y   `1001 000d dddd 1010`
5209467b48Spatrick ///
5309467b48Spatrick /// ld Rd, Z    `1000 000d dddd 0000`
5409467b48Spatrick /// ld Rd, Z+   `1001 000d dddd 0001`
5509467b48Spatrick /// ld Rd, -Z   `1001 000d dddd 0010`
5609467b48Spatrick ///                 ^
5709467b48Spatrick ///                 |
5809467b48Spatrick /// Note this one inconsistent bit - it is 1 sometimes and 0 at other times.
5909467b48Spatrick /// There is no logical pattern. Looking at a truth table, the following
6009467b48Spatrick /// formula can be derived to fit the pattern:
6109467b48Spatrick //
6209467b48Spatrick /// ```
6309467b48Spatrick /// inconsistent_bit = is_predec OR is_postinc OR is_reg_x
6409467b48Spatrick /// ```
6509467b48Spatrick //
6609467b48Spatrick /// We manually set this bit in this post encoder method.
6709467b48Spatrick unsigned
loadStorePostEncoder(const MCInst & MI,unsigned EncodedValue,const MCSubtargetInfo & STI) const6809467b48Spatrick AVRMCCodeEmitter::loadStorePostEncoder(const MCInst &MI, unsigned EncodedValue,
6909467b48Spatrick                                        const MCSubtargetInfo &STI) const {
7009467b48Spatrick 
7109467b48Spatrick   assert(MI.getOperand(0).isReg() && MI.getOperand(1).isReg() &&
7209467b48Spatrick          "the load/store operands must be registers");
7309467b48Spatrick 
7409467b48Spatrick   unsigned Opcode = MI.getOpcode();
7509467b48Spatrick 
7609467b48Spatrick   // check whether either of the registers are the X pointer register.
7709467b48Spatrick   bool IsRegX = MI.getOperand(0).getReg() == AVR::R27R26 ||
7809467b48Spatrick                 MI.getOperand(1).getReg() == AVR::R27R26;
7909467b48Spatrick 
8009467b48Spatrick   bool IsPredec = Opcode == AVR::LDRdPtrPd || Opcode == AVR::STPtrPdRr;
8109467b48Spatrick   bool IsPostinc = Opcode == AVR::LDRdPtrPi || Opcode == AVR::STPtrPiRr;
8209467b48Spatrick 
8309467b48Spatrick   // Check if we need to set the inconsistent bit
8409467b48Spatrick   if (IsRegX || IsPredec || IsPostinc) {
8509467b48Spatrick     EncodedValue |= (1 << 12);
8609467b48Spatrick   }
8709467b48Spatrick 
8809467b48Spatrick   return EncodedValue;
8909467b48Spatrick }
9009467b48Spatrick 
9109467b48Spatrick template <AVR::Fixups Fixup>
9209467b48Spatrick unsigned
encodeRelCondBrTarget(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const9309467b48Spatrick AVRMCCodeEmitter::encodeRelCondBrTarget(const MCInst &MI, unsigned OpNo,
9409467b48Spatrick                                         SmallVectorImpl<MCFixup> &Fixups,
9509467b48Spatrick                                         const MCSubtargetInfo &STI) const {
9609467b48Spatrick   const MCOperand &MO = MI.getOperand(OpNo);
9709467b48Spatrick 
9809467b48Spatrick   if (MO.isExpr()) {
99*d415bd75Srobert     Fixups.push_back(
100*d415bd75Srobert         MCFixup::create(0, MO.getExpr(), MCFixupKind(Fixup), MI.getLoc()));
10109467b48Spatrick     return 0;
10209467b48Spatrick   }
10309467b48Spatrick 
10409467b48Spatrick   assert(MO.isImm());
10509467b48Spatrick 
10609467b48Spatrick   // Take the size of the current instruction away.
10709467b48Spatrick   // With labels, this is implicitly done.
10809467b48Spatrick   auto target = MO.getImm();
10909467b48Spatrick   AVR::fixups::adjustBranchTarget(target);
11009467b48Spatrick   return target;
11109467b48Spatrick }
11209467b48Spatrick 
encodeLDSTPtrReg(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const11309467b48Spatrick unsigned AVRMCCodeEmitter::encodeLDSTPtrReg(const MCInst &MI, unsigned OpNo,
11409467b48Spatrick                                             SmallVectorImpl<MCFixup> &Fixups,
11509467b48Spatrick                                             const MCSubtargetInfo &STI) const {
11609467b48Spatrick   auto MO = MI.getOperand(OpNo);
11709467b48Spatrick 
11809467b48Spatrick   // The operand should be a pointer register.
11909467b48Spatrick   assert(MO.isReg());
12009467b48Spatrick 
12109467b48Spatrick   switch (MO.getReg()) {
122*d415bd75Srobert   case AVR::R27R26:
123*d415bd75Srobert     return 0x03; // X: 0b11
124*d415bd75Srobert   case AVR::R29R28:
125*d415bd75Srobert     return 0x02; // Y: 0b10
126*d415bd75Srobert   case AVR::R31R30:
127*d415bd75Srobert     return 0x00; // Z: 0b00
12809467b48Spatrick   default:
12909467b48Spatrick     llvm_unreachable("invalid pointer register");
13009467b48Spatrick   }
13109467b48Spatrick }
13209467b48Spatrick 
13309467b48Spatrick /// Encodes a `memri` operand.
13409467b48Spatrick /// The operand is 7-bits.
13509467b48Spatrick /// * The lower 6 bits is the immediate
13609467b48Spatrick /// * The upper bit is the pointer register bit (Z=0,Y=1)
encodeMemri(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const13709467b48Spatrick unsigned AVRMCCodeEmitter::encodeMemri(const MCInst &MI, unsigned OpNo,
13809467b48Spatrick                                        SmallVectorImpl<MCFixup> &Fixups,
13909467b48Spatrick                                        const MCSubtargetInfo &STI) const {
14009467b48Spatrick   auto RegOp = MI.getOperand(OpNo);
14109467b48Spatrick   auto OffsetOp = MI.getOperand(OpNo + 1);
14209467b48Spatrick 
14309467b48Spatrick   assert(RegOp.isReg() && "Expected register operand");
14409467b48Spatrick 
14509467b48Spatrick   uint8_t RegBit = 0;
14609467b48Spatrick 
14709467b48Spatrick   switch (RegOp.getReg()) {
14809467b48Spatrick   default:
14909467b48Spatrick     llvm_unreachable("Expected either Y or Z register");
15009467b48Spatrick   case AVR::R31R30:
15109467b48Spatrick     RegBit = 0;
15209467b48Spatrick     break; // Z register
15309467b48Spatrick   case AVR::R29R28:
15409467b48Spatrick     RegBit = 1;
15509467b48Spatrick     break; // Y register
15609467b48Spatrick   }
15709467b48Spatrick 
15809467b48Spatrick   int8_t OffsetBits;
15909467b48Spatrick 
16009467b48Spatrick   if (OffsetOp.isImm()) {
16109467b48Spatrick     OffsetBits = OffsetOp.getImm();
16209467b48Spatrick   } else if (OffsetOp.isExpr()) {
16309467b48Spatrick     OffsetBits = 0;
16409467b48Spatrick     Fixups.push_back(MCFixup::create(0, OffsetOp.getExpr(),
16509467b48Spatrick                                      MCFixupKind(AVR::fixup_6), MI.getLoc()));
16609467b48Spatrick   } else {
16709467b48Spatrick     llvm_unreachable("invalid value for offset");
16809467b48Spatrick   }
16909467b48Spatrick 
17009467b48Spatrick   return (RegBit << 6) | OffsetBits;
17109467b48Spatrick }
17209467b48Spatrick 
encodeComplement(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const17309467b48Spatrick unsigned AVRMCCodeEmitter::encodeComplement(const MCInst &MI, unsigned OpNo,
17409467b48Spatrick                                             SmallVectorImpl<MCFixup> &Fixups,
17509467b48Spatrick                                             const MCSubtargetInfo &STI) const {
17609467b48Spatrick   // The operand should be an immediate.
17709467b48Spatrick   assert(MI.getOperand(OpNo).isImm());
17809467b48Spatrick 
17909467b48Spatrick   auto Imm = MI.getOperand(OpNo).getImm();
18009467b48Spatrick   return (~0) - Imm;
18109467b48Spatrick }
18209467b48Spatrick 
18309467b48Spatrick template <AVR::Fixups Fixup, unsigned Offset>
encodeImm(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const18409467b48Spatrick unsigned AVRMCCodeEmitter::encodeImm(const MCInst &MI, unsigned OpNo,
18509467b48Spatrick                                      SmallVectorImpl<MCFixup> &Fixups,
18609467b48Spatrick                                      const MCSubtargetInfo &STI) const {
18709467b48Spatrick   auto MO = MI.getOperand(OpNo);
18809467b48Spatrick 
18909467b48Spatrick   if (MO.isExpr()) {
19009467b48Spatrick     if (isa<AVRMCExpr>(MO.getExpr())) {
19109467b48Spatrick       // If the expression is already an AVRMCExpr (i.e. a lo8(symbol),
19209467b48Spatrick       // we shouldn't perform any more fixups. Without this check, we would
19309467b48Spatrick       // instead create a fixup to the symbol named 'lo8(symbol)' which
19409467b48Spatrick       // is not correct.
19509467b48Spatrick       return getExprOpValue(MO.getExpr(), Fixups, STI);
19609467b48Spatrick     }
19709467b48Spatrick 
19809467b48Spatrick     MCFixupKind FixupKind = static_cast<MCFixupKind>(Fixup);
199*d415bd75Srobert     Fixups.push_back(
200*d415bd75Srobert         MCFixup::create(Offset, MO.getExpr(), FixupKind, MI.getLoc()));
20109467b48Spatrick 
20209467b48Spatrick     return 0;
20309467b48Spatrick   }
20409467b48Spatrick 
20509467b48Spatrick   assert(MO.isImm());
20609467b48Spatrick   return MO.getImm();
20709467b48Spatrick }
20809467b48Spatrick 
encodeCallTarget(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const20909467b48Spatrick unsigned AVRMCCodeEmitter::encodeCallTarget(const MCInst &MI, unsigned OpNo,
21009467b48Spatrick                                             SmallVectorImpl<MCFixup> &Fixups,
21109467b48Spatrick                                             const MCSubtargetInfo &STI) const {
21209467b48Spatrick   auto MO = MI.getOperand(OpNo);
21309467b48Spatrick 
21409467b48Spatrick   if (MO.isExpr()) {
21509467b48Spatrick     MCFixupKind FixupKind = static_cast<MCFixupKind>(AVR::fixup_call);
21609467b48Spatrick     Fixups.push_back(MCFixup::create(0, MO.getExpr(), FixupKind, MI.getLoc()));
21709467b48Spatrick     return 0;
21809467b48Spatrick   }
21909467b48Spatrick 
22009467b48Spatrick   assert(MO.isImm());
22109467b48Spatrick 
22209467b48Spatrick   auto Target = MO.getImm();
22309467b48Spatrick   AVR::fixups::adjustBranchTarget(Target);
22409467b48Spatrick   return Target;
22509467b48Spatrick }
22609467b48Spatrick 
getExprOpValue(const MCExpr * Expr,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const22709467b48Spatrick unsigned AVRMCCodeEmitter::getExprOpValue(const MCExpr *Expr,
22809467b48Spatrick                                           SmallVectorImpl<MCFixup> &Fixups,
22909467b48Spatrick                                           const MCSubtargetInfo &STI) const {
23009467b48Spatrick 
23109467b48Spatrick   MCExpr::ExprKind Kind = Expr->getKind();
23209467b48Spatrick 
23309467b48Spatrick   if (Kind == MCExpr::Binary) {
23409467b48Spatrick     Expr = static_cast<const MCBinaryExpr *>(Expr)->getLHS();
23509467b48Spatrick     Kind = Expr->getKind();
23609467b48Spatrick   }
23709467b48Spatrick 
23809467b48Spatrick   if (Kind == MCExpr::Target) {
23909467b48Spatrick     AVRMCExpr const *AVRExpr = cast<AVRMCExpr>(Expr);
24009467b48Spatrick     int64_t Result;
24109467b48Spatrick     if (AVRExpr->evaluateAsConstant(Result)) {
24209467b48Spatrick       return Result;
24309467b48Spatrick     }
24409467b48Spatrick 
24509467b48Spatrick     MCFixupKind FixupKind = static_cast<MCFixupKind>(AVRExpr->getFixupKind());
24609467b48Spatrick     Fixups.push_back(MCFixup::create(0, AVRExpr, FixupKind));
24709467b48Spatrick     return 0;
24809467b48Spatrick   }
24909467b48Spatrick 
25009467b48Spatrick   assert(Kind == MCExpr::SymbolRef);
25109467b48Spatrick   return 0;
25209467b48Spatrick }
25309467b48Spatrick 
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const25409467b48Spatrick unsigned AVRMCCodeEmitter::getMachineOpValue(const MCInst &MI,
25509467b48Spatrick                                              const MCOperand &MO,
25609467b48Spatrick                                              SmallVectorImpl<MCFixup> &Fixups,
25709467b48Spatrick                                              const MCSubtargetInfo &STI) const {
258*d415bd75Srobert   if (MO.isReg())
259*d415bd75Srobert     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
260*d415bd75Srobert   if (MO.isImm())
261*d415bd75Srobert     return static_cast<unsigned>(MO.getImm());
26209467b48Spatrick 
26373471bf0Spatrick   if (MO.isDFPImm())
26473471bf0Spatrick     return static_cast<unsigned>(bit_cast<double>(MO.getDFPImm()));
26509467b48Spatrick 
26609467b48Spatrick   // MO must be an Expr.
26709467b48Spatrick   assert(MO.isExpr());
26809467b48Spatrick 
26909467b48Spatrick   return getExprOpValue(MO.getExpr(), Fixups, STI);
27009467b48Spatrick }
27109467b48Spatrick 
emitInstruction(uint64_t Val,unsigned Size,const MCSubtargetInfo & STI,raw_ostream & OS) const27209467b48Spatrick void AVRMCCodeEmitter::emitInstruction(uint64_t Val, unsigned Size,
27309467b48Spatrick                                        const MCSubtargetInfo &STI,
27409467b48Spatrick                                        raw_ostream &OS) const {
27509467b48Spatrick   size_t WordCount = Size / 2;
27609467b48Spatrick 
27709467b48Spatrick   for (int64_t i = WordCount - 1; i >= 0; --i) {
27809467b48Spatrick     uint16_t Word = (Val >> (i * 16)) & 0xFFFF;
27909467b48Spatrick     support::endian::write(OS, Word, support::endianness::little);
28009467b48Spatrick   }
28109467b48Spatrick }
28209467b48Spatrick 
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const28309467b48Spatrick void AVRMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
28409467b48Spatrick                                          SmallVectorImpl<MCFixup> &Fixups,
28509467b48Spatrick                                          const MCSubtargetInfo &STI) const {
28609467b48Spatrick   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
28709467b48Spatrick 
28809467b48Spatrick   // Get byte count of instruction
28909467b48Spatrick   unsigned Size = Desc.getSize();
29009467b48Spatrick 
29109467b48Spatrick   assert(Size > 0 && "Instruction size cannot be zero");
29209467b48Spatrick 
29309467b48Spatrick   uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);
29409467b48Spatrick   emitInstruction(BinaryOpCode, Size, STI, OS);
29509467b48Spatrick }
29609467b48Spatrick 
createAVRMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)29709467b48Spatrick MCCodeEmitter *createAVRMCCodeEmitter(const MCInstrInfo &MCII,
29809467b48Spatrick                                       MCContext &Ctx) {
29909467b48Spatrick   return new AVRMCCodeEmitter(MCII, Ctx);
30009467b48Spatrick }
30109467b48Spatrick 
30209467b48Spatrick #include "AVRGenMCCodeEmitter.inc"
30309467b48Spatrick 
30409467b48Spatrick } // end of namespace llvm
305