Home | History | Annotate | Download | only in InstPrinter
      1 //===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===//
      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 // This class prints an AVR MCInst to a .s file.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "AVRInstPrinter.h"
     15 
     16 #include "MCTargetDesc/AVRMCTargetDesc.h"
     17 
     18 #include "llvm/MC/MCExpr.h"
     19 #include "llvm/MC/MCInst.h"
     20 #include "llvm/MC/MCInstrDesc.h"
     21 #include "llvm/MC/MCInstrInfo.h"
     22 #include "llvm/MC/MCRegisterInfo.h"
     23 #include "llvm/Support/ErrorHandling.h"
     24 #include "llvm/Support/FormattedStream.h"
     25 
     26 #include <cstring>
     27 
     28 #define DEBUG_TYPE "asm-printer"
     29 
     30 namespace llvm {
     31 
     32 // Include the auto-generated portion of the assembly writer.
     33 #define PRINT_ALIAS_INSTR
     34 #include "AVRGenAsmWriter.inc"
     35 
     36 void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
     37                                StringRef Annot, const MCSubtargetInfo &STI) {
     38   unsigned Opcode = MI->getOpcode();
     39 
     40   // First handle load and store instructions with postinc or predec
     41   // of the form "ld reg, X+".
     42   // TODO: We should be able to rewrite this using TableGen data.
     43   switch (Opcode) {
     44   case AVR::LDRdPtr:
     45   case AVR::LDRdPtrPi:
     46   case AVR::LDRdPtrPd:
     47     O << "\tld\t";
     48     printOperand(MI, 0, O);
     49     O << ", ";
     50 
     51     if (Opcode == AVR::LDRdPtrPd)
     52       O << '-';
     53 
     54     printOperand(MI, 1, O);
     55 
     56     if (Opcode == AVR::LDRdPtrPi)
     57       O << '+';
     58     break;
     59   case AVR::STPtrRr:
     60     O << "\tst\t";
     61     printOperand(MI, 0, O);
     62     O << ", ";
     63     printOperand(MI, 1, O);
     64     break;
     65   case AVR::STPtrPiRr:
     66   case AVR::STPtrPdRr:
     67     O << "\tst\t";
     68 
     69     if (Opcode == AVR::STPtrPdRr)
     70       O << '-';
     71 
     72     printOperand(MI, 1, O);
     73 
     74     if (Opcode == AVR::STPtrPiRr)
     75       O << '+';
     76 
     77     O << ", ";
     78     printOperand(MI, 2, O);
     79     break;
     80   default:
     81     if (!printAliasInstr(MI, O))
     82       printInstruction(MI, O);
     83 
     84     printAnnotation(O, Annot);
     85     break;
     86   }
     87 }
     88 
     89 const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum,
     90                                                   MCRegisterInfo const &MRI) {
     91   // GCC prints register pairs by just printing the lower register
     92   // If the register contains a subregister, print it instead
     93   if (MRI.getNumSubRegIndices() > 0) {
     94     unsigned RegLoNum = MRI.getSubReg(RegNum, AVR::sub_lo);
     95     RegNum = (RegLoNum != AVR::NoRegister) ? RegLoNum : RegNum;
     96   }
     97 
     98   return getRegisterName(RegNum);
     99 }
    100 
    101 void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
    102                                   raw_ostream &O) {
    103   const MCOperand &Op = MI->getOperand(OpNo);
    104   const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo];
    105 
    106   if (Op.isReg()) {
    107     bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
    108                     (MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
    109                     (MOI.RegClass == AVR::ZREGRegClassID);
    110 
    111     if (isPtrReg) {
    112       O << getRegisterName(Op.getReg(), AVR::ptr);
    113     } else {
    114       O << getPrettyRegisterName(Op.getReg(), MRI);
    115     }
    116   } else if (Op.isImm()) {
    117     O << Op.getImm();
    118   } else {
    119     assert(Op.isExpr() && "Unknown operand kind in printOperand");
    120     O << *Op.getExpr();
    121   }
    122 }
    123 
    124 /// This is used to print an immediate value that ends up
    125 /// being encoded as a pc-relative value.
    126 void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
    127                                    raw_ostream &O) {
    128   const MCOperand &Op = MI->getOperand(OpNo);
    129 
    130   if (Op.isImm()) {
    131     int64_t Imm = Op.getImm();
    132     O << '.';
    133 
    134     // Print a position sign if needed.
    135     // Negative values have their sign printed automatically.
    136     if (Imm >= 0)
    137       O << '+';
    138 
    139     O << Imm;
    140   } else {
    141     assert(Op.isExpr() && "Unknown pcrel immediate operand");
    142     O << *Op.getExpr();
    143   }
    144 }
    145 
    146 void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,
    147                                 raw_ostream &O) {
    148   assert(MI->getOperand(OpNo).isReg() && "Expected a register for the first operand");
    149 
    150   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
    151 
    152   // Print the register.
    153   printOperand(MI, OpNo, O);
    154 
    155   // Print the {+,-}offset.
    156   if (OffsetOp.isImm()) {
    157     int64_t Offset = OffsetOp.getImm();
    158 
    159     if (Offset >= 0)
    160       O << '+';
    161 
    162     O << Offset;
    163   } else if (OffsetOp.isExpr()) {
    164     O << *OffsetOp.getExpr();
    165   } else {
    166     llvm_unreachable("unknown type for offset");
    167   }
    168 }
    169 
    170 } // end of namespace llvm
    171 
    172