1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-24 13:33:37 +02:00
llvm-mirror/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.cpp
Ulrich Weigand c8db580954 [SystemZ] Support all TLS access models - MC part
The current SystemZ back-end only supports the local-exec TLS access model.
This patch adds all required MC support for the other TLS models, which
means in particular:

- Support additional relocation types for
  Initial-exec model: R_390_TLS_IEENT
  Local-dynamic-model: R_390_TLS_LDO32, R_390_TLS_LDO64,
                       R_390_TLS_LDM32, R_390_TLS_LDM64, R_390_TLS_LDCALL
  General-dynamic model: R_390_TLS_GD32, R_390_TLS_GD64, R_390_TLS_GDCALL

- Support assembler syntax to generate additional relocations
  for use with __tls_get_offset calls:
    :tls_gdcall:
    :tls_ldcall:

The patch also adds a new test to verify fixups and relocations,
and removes the (already unused) FK_390_PLT16DBL/FK_390_PLT32DBL
fixup kinds.

llvm-svn: 229652
2015-02-18 09:11:36 +00:00

190 lines
6.3 KiB
C++

//===-- SystemZInstPrinter.cpp - Convert SystemZ 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.
//
//===----------------------------------------------------------------------===//
#include "SystemZInstPrinter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
#include "SystemZGenAsmWriter.inc"
void SystemZInstPrinter::printAddress(unsigned Base, int64_t Disp,
unsigned Index, raw_ostream &O) {
O << Disp;
if (Base) {
O << '(';
if (Index)
O << '%' << getRegisterName(Index) << ',';
O << '%' << getRegisterName(Base) << ')';
} else
assert(!Index && "Shouldn't have an index without a base");
}
void SystemZInstPrinter::printOperand(const MCOperand &MO, raw_ostream &O) {
if (MO.isReg())
O << '%' << getRegisterName(MO.getReg());
else if (MO.isImm())
O << MO.getImm();
else if (MO.isExpr())
O << *MO.getExpr();
else
llvm_unreachable("Invalid operand");
}
void SystemZInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot) {
printInstruction(MI, O);
printAnnotation(O, Annot);
}
void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
O << '%' << getRegisterName(RegNo);
}
void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<4>(Value) && "Invalid u4imm argument");
O << Value;
}
void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<6>(Value) && "Invalid u6imm argument");
O << Value;
}
void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isInt<8>(Value) && "Invalid s8imm argument");
O << Value;
}
void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<8>(Value) && "Invalid u8imm argument");
O << Value;
}
void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isInt<16>(Value) && "Invalid s16imm argument");
O << Value;
}
void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<16>(Value) && "Invalid u16imm argument");
O << Value;
}
void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isInt<32>(Value) && "Invalid s32imm argument");
O << Value;
}
void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<32>(Value) && "Invalid u32imm argument");
O << Value;
}
void SystemZInstPrinter::printAccessRegOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
uint64_t Value = MI->getOperand(OpNum).getImm();
assert(Value < 16 && "Invalid access register number");
O << "%a" << (unsigned int)Value;
}
void SystemZInstPrinter::printPCRelOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNum);
if (MO.isImm()) {
O << "0x";
O.write_hex(MO.getImm());
} else
O << *MO.getExpr();
}
void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
// Output the PC-relative operand.
printPCRelOperand(MI, OpNum, O);
// Output the TLS marker if present.
if ((unsigned)OpNum + 1 < MI->getNumOperands()) {
const MCOperand &MO = MI->getOperand(OpNum + 1);
const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*MO.getExpr());
switch (refExp.getKind()) {
case MCSymbolRefExpr::VK_TLSGD:
O << ":tls_gdcall:";
break;
case MCSymbolRefExpr::VK_TLSLDM:
O << ":tls_ldcall:";
break;
default:
llvm_unreachable("Unexpected symbol kind");
}
O << refExp.getSymbol().getName();
}
}
void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printOperand(MI->getOperand(OpNum), O);
}
void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printAddress(MI->getOperand(OpNum).getReg(),
MI->getOperand(OpNum + 1).getImm(), 0, O);
}
void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printAddress(MI->getOperand(OpNum).getReg(),
MI->getOperand(OpNum + 1).getImm(),
MI->getOperand(OpNum + 2).getReg(), O);
}
void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
unsigned Base = MI->getOperand(OpNum).getReg();
uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
uint64_t Length = MI->getOperand(OpNum + 2).getImm();
O << Disp << '(' << Length;
if (Base)
O << ",%" << getRegisterName(Base);
O << ')';
}
void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
raw_ostream &O) {
static const char *const CondNames[] = {
"o", "h", "nle", "l", "nhe", "lh", "ne",
"e", "nlh", "he", "nl", "le", "nh", "no"
};
uint64_t Imm = MI->getOperand(OpNum).getImm();
assert(Imm > 0 && Imm < 15 && "Invalid condition");
O << CondNames[Imm - 1];
}