//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints an ARM MCInst to a .s file.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "ARMInstPrinter.h"
#include "MCTargetDesc/ARMBaseInfo.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define GET_INSTRUCTION_NAME
#include "ARMGenAsmWriter.inc"
/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
///
/// getSORegOffset returns an integer from 0-31, but '0' should actually be printed
/// 32 as the immediate shouldbe within the range 1-32.
static unsigned translateShiftImm(unsigned imm) {
if (imm == 0)
return 32;
return imm;
}
ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI,
const MCSubtargetInfo &STI) :
MCInstPrinter(MAI) {
// Initialize the set of available features.
setAvailableFeatures(STI.getFeatureBits());
}
StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const {
return getInstructionName(Opcode);
}
void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
OS << getRegisterName(RegNo);
}
void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot) {
unsigned Opcode = MI->getOpcode();
// Check for MOVs and print canonical forms, instead.
if (Opcode == ARM::MOVsr) {
// FIXME: Thumb variants?
const MCOperand &Dst = MI->getOperand(0);
const MCOperand &MO1 = MI->getOperand(1);
const MCOperand &MO2 = MI->getOperand(2);
const MCOperand &MO3 = MI->getOperand(3);
O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
printSBitModifierOperand(MI, 6, O);
printPredicateOperand(MI, 4, O);
O << '\t' << getRegisterName(Dst.getReg())
<< ", " << getRegisterName(MO1.getReg());
O << ", " << getRegisterName(MO2.getReg());
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
if (CommentStream) printAnnotation(*CommentStream, Annot);
return;
}
if (Opcode == ARM::MOVsi) {
// FIXME: Thumb variants?
const MCOperand &Dst = MI->getOperand(0);
const MCOperand &MO1 = MI->getOperand(1);
const MCOperand &MO2 = MI->getOperand(2);
O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
printSBitModifierOperand(MI, 5, O);
printPredicateOperand(MI, 3, O);
O << '\t' << getRegisterName(Dst.getReg())
<< ", " << getRegisterName(MO1.getReg());
if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {
if (CommentStream) printAnnotation(*CommentStream, Annot);
return;
}
O << ", #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
if (CommentStream) printAnnotation(*CommentStream, Annot);
return;
}
// A8.6.123 PUSH
if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) &&
MI->getOperand(0).getReg() == ARM::SP) {
O << '\t' << "push";
printPredicateOperand(MI, 2, O);
if (Opcode == ARM::t2STMDB_UPD)
O << ".w";
O << '\t';
printRegisterList(MI, 4, O);
if (CommentStream) printAnnotation(*CommentStream, Annot);
return;
}
if (Opcode == ARM::STR_PRE_IMM && MI->getOperand(2).getReg() == ARM::SP &&
MI->getOperand(3).getImm() == -4) {
O << '\t' << "push";
printPredicateOperand(MI, 4, O);
O << "\t{" << getRegisterName(MI->getOperand(1).getReg()) << "}";
if (CommentStream) printAnnotation(*CommentStream, Annot);
return;
}