forked from OSchip/llvm-project
166 lines
5.4 KiB
C
166 lines
5.4 KiB
C
|
//===-- HexagonAsmPrinter.h - Print machine code to an Hexagon .s file ----===//
|
||
|
//
|
||
|
// The LLVM Compiler Infrastructure
|
||
|
//
|
||
|
// This file is distributed under the University of Illinois Open Source
|
||
|
// License. See LICENSE.TXT for details.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// Hexagon Assembly printer class.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#ifndef HEXAGONASMPRINTER_H
|
||
|
#define HEXAGONASMPRINTER_H
|
||
|
|
||
|
#include "Hexagon.h"
|
||
|
#include "HexagonTargetMachine.h"
|
||
|
#include "llvm/CodeGen/AsmPrinter.h"
|
||
|
#include "llvm/Support/Compiler.h"
|
||
|
#include "llvm/Support/raw_ostream.h"
|
||
|
|
||
|
namespace llvm {
|
||
|
class HexagonAsmPrinter : public AsmPrinter {
|
||
|
const HexagonSubtarget *Subtarget;
|
||
|
|
||
|
public:
|
||
|
explicit HexagonAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
||
|
: AsmPrinter(TM, Streamer) {
|
||
|
Subtarget = &TM.getSubtarget<HexagonSubtarget>();
|
||
|
}
|
||
|
|
||
|
virtual const char *getPassName() const {
|
||
|
return "Hexagon Assembly Printer";
|
||
|
}
|
||
|
|
||
|
bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const;
|
||
|
|
||
|
virtual void EmitInstruction(const MachineInstr *MI);
|
||
|
virtual void EmitAlignment(unsigned NumBits,
|
||
|
const GlobalValue *GV = 0) const;
|
||
|
|
||
|
void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
|
||
|
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
unsigned AsmVariant, const char *ExtraCode,
|
||
|
raw_ostream &OS);
|
||
|
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
unsigned AsmVariant, const char *ExtraCode,
|
||
|
raw_ostream &OS);
|
||
|
|
||
|
/// printInstruction - This method is automatically generated by tablegen
|
||
|
/// from the instruction set description. This method returns true if the
|
||
|
/// machine instruction was sufficiently described to print it, otherwise it
|
||
|
/// returns false.
|
||
|
void printInstruction(const MachineInstr *MI, raw_ostream &O);
|
||
|
|
||
|
// void printMachineInstruction(const MachineInstr *MI);
|
||
|
void printOp(const MachineOperand &MO, raw_ostream &O);
|
||
|
|
||
|
/// printRegister - Print register according to target requirements.
|
||
|
///
|
||
|
void printRegister(const MachineOperand &MO, bool R0AsZero,
|
||
|
raw_ostream &O) {
|
||
|
unsigned RegNo = MO.getReg();
|
||
|
assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??");
|
||
|
O << getRegisterName(RegNo);
|
||
|
}
|
||
|
|
||
|
void printImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
raw_ostream &O) {
|
||
|
int value = MI->getOperand(OpNo).getImm();
|
||
|
O << value;
|
||
|
}
|
||
|
|
||
|
void printNegImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
raw_ostream &O) {
|
||
|
int value = MI->getOperand(OpNo).getImm();
|
||
|
O << -value;
|
||
|
}
|
||
|
|
||
|
void printMEMriOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
raw_ostream &O) {
|
||
|
const MachineOperand &MO1 = MI->getOperand(OpNo);
|
||
|
const MachineOperand &MO2 = MI->getOperand(OpNo+1);
|
||
|
|
||
|
O << getRegisterName(MO1.getReg())
|
||
|
<< " + #"
|
||
|
<< (int) MO2.getImm();
|
||
|
}
|
||
|
|
||
|
void printFrameIndexOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
raw_ostream &O) {
|
||
|
const MachineOperand &MO1 = MI->getOperand(OpNo);
|
||
|
const MachineOperand &MO2 = MI->getOperand(OpNo+1);
|
||
|
|
||
|
O << getRegisterName(MO1.getReg())
|
||
|
<< ", #"
|
||
|
<< MO2.getImm();
|
||
|
}
|
||
|
|
||
|
void printBranchOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
raw_ostream &O) {
|
||
|
// Branches can take an immediate operand. This is used by the branch
|
||
|
// selection pass to print $+8, an eight byte displacement from the PC.
|
||
|
if (MI->getOperand(OpNo).isImm()) {
|
||
|
O << "$+" << MI->getOperand(OpNo).getImm()*4;
|
||
|
} else {
|
||
|
printOp(MI->getOperand(OpNo), O);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void printCallOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
raw_ostream &O) {
|
||
|
}
|
||
|
|
||
|
void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
raw_ostream &O) {
|
||
|
}
|
||
|
|
||
|
void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||
|
O << "#HI(";
|
||
|
if (MI->getOperand(OpNo).isImm()) {
|
||
|
printImmOperand(MI, OpNo, O);
|
||
|
}
|
||
|
else {
|
||
|
printOp(MI->getOperand(OpNo), O);
|
||
|
}
|
||
|
O << ")";
|
||
|
}
|
||
|
|
||
|
void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||
|
O << "#HI(";
|
||
|
if (MI->getOperand(OpNo).isImm()) {
|
||
|
printImmOperand(MI, OpNo, O);
|
||
|
}
|
||
|
else {
|
||
|
printOp(MI->getOperand(OpNo), O);
|
||
|
}
|
||
|
O << ")";
|
||
|
}
|
||
|
|
||
|
void printPredicateOperand(const MachineInstr *MI, unsigned OpNo,
|
||
|
raw_ostream &O);
|
||
|
|
||
|
#if 0
|
||
|
void printModuleLevelGV(const GlobalVariable* GVar, raw_ostream &O);
|
||
|
#endif
|
||
|
|
||
|
void printAddrModeBasePlusOffset(const MachineInstr *MI, int OpNo,
|
||
|
raw_ostream &O);
|
||
|
|
||
|
void printGlobalOperand(const MachineInstr *MI, int OpNo, raw_ostream &O);
|
||
|
void printJumpTable(const MachineInstr *MI, int OpNo, raw_ostream &O);
|
||
|
void printConstantPool(const MachineInstr *MI, int OpNo, raw_ostream &O);
|
||
|
|
||
|
static const char *getRegisterName(unsigned RegNo);
|
||
|
|
||
|
#if 0
|
||
|
void EmitStartOfAsmFile(Module &M);
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
} // end of llvm namespace
|
||
|
|
||
|
#endif
|