2017-02-04 00:39:06 +01:00
|
|
|
//===- SystemZInstPrinter.cpp - Convert SystemZ MCInst to assembly syntax -===//
|
2013-05-06 18:15:19 +02:00
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2013-05-06 18:15:19 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "SystemZInstPrinter.h"
|
|
|
|
#include "llvm/MC/MCExpr.h"
|
2015-05-15 23:58:42 +02:00
|
|
|
#include "llvm/MC/MCInst.h"
|
2015-02-18 10:11:36 +01:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2017-02-04 00:39:06 +01:00
|
|
|
#include "llvm/Support/Casting.h"
|
2015-05-15 23:58:42 +02:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2017-02-04 00:39:06 +01:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2013-05-06 18:15:19 +02:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-02-04 00:39:06 +01:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
2013-05-06 18:15:19 +02:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 04:41:26 +02:00
|
|
|
#define DEBUG_TYPE "asm-printer"
|
|
|
|
|
2013-05-06 18:15:19 +02:00
|
|
|
#include "SystemZGenAsmWriter.inc"
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printAddress(unsigned Base, int64_t Disp,
|
|
|
|
unsigned Index, raw_ostream &O) {
|
|
|
|
O << Disp;
|
2015-05-05 21:23:40 +02:00
|
|
|
if (Base || Index) {
|
2013-05-06 18:15:19 +02:00
|
|
|
O << '(';
|
2015-05-05 21:23:40 +02:00
|
|
|
if (Index) {
|
|
|
|
O << '%' << getRegisterName(Index);
|
|
|
|
if (Base)
|
|
|
|
O << ',';
|
|
|
|
}
|
|
|
|
if (Base)
|
|
|
|
O << '%' << getRegisterName(Base);
|
|
|
|
O << ')';
|
|
|
|
}
|
2013-05-06 18:15:19 +02:00
|
|
|
}
|
|
|
|
|
2015-06-09 02:31:39 +02:00
|
|
|
void SystemZInstPrinter::printOperand(const MCOperand &MO, const MCAsmInfo *MAI,
|
|
|
|
raw_ostream &O) {
|
2019-11-26 11:16:48 +01:00
|
|
|
if (MO.isReg()) {
|
|
|
|
if (!MO.getReg())
|
|
|
|
O << '0';
|
|
|
|
else
|
|
|
|
O << '%' << getRegisterName(MO.getReg());
|
|
|
|
}
|
2013-05-06 18:15:19 +02:00
|
|
|
else if (MO.isImm())
|
|
|
|
O << MO.getImm();
|
|
|
|
else if (MO.isExpr())
|
2015-06-09 02:31:39 +02:00
|
|
|
MO.getExpr()->print(O, MAI);
|
2013-05-06 18:15:19 +02:00
|
|
|
else
|
|
|
|
llvm_unreachable("Invalid operand");
|
|
|
|
}
|
|
|
|
|
2020-01-03 19:55:30 +01:00
|
|
|
void SystemZInstPrinter::printInst(const MCInst *MI, uint64_t Address,
|
|
|
|
StringRef Annot, const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
2020-01-03 21:02:46 +01:00
|
|
|
printInstruction(MI, Address, O);
|
2013-05-06 18:15:19 +02:00
|
|
|
printAnnotation(O, Annot);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
|
|
|
|
O << '%' << getRegisterName(RegNo);
|
|
|
|
}
|
|
|
|
|
2015-10-28 14:54:36 +01:00
|
|
|
template <unsigned N>
|
|
|
|
static void printUImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
|
2013-05-06 18:15:19 +02:00
|
|
|
int64_t Value = MI->getOperand(OpNum).getImm();
|
2015-05-05 21:23:40 +02:00
|
|
|
assert(isUInt<N>(Value) && "Invalid uimm argument");
|
2013-05-06 18:15:19 +02:00
|
|
|
O << Value;
|
|
|
|
}
|
|
|
|
|
2015-10-28 14:54:36 +01:00
|
|
|
template <unsigned N>
|
|
|
|
static void printSImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
|
2013-05-06 18:15:19 +02:00
|
|
|
int64_t Value = MI->getOperand(OpNum).getImm();
|
2015-05-05 21:23:40 +02:00
|
|
|
assert(isInt<N>(Value) && "Invalid simm argument");
|
2013-05-06 18:15:19 +02:00
|
|
|
O << Value;
|
|
|
|
}
|
|
|
|
|
2015-05-05 21:23:40 +02:00
|
|
|
void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printUImmOperand<1>(MI, OpNum, O);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printUImmOperand<2>(MI, OpNum, O);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printUImmOperand<3>(MI, OpNum, O);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printUImmOperand<4>(MI, OpNum, O);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printUImmOperand<6>(MI, OpNum, O);
|
|
|
|
}
|
|
|
|
|
2013-05-06 18:15:19 +02:00
|
|
|
void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
2015-05-05 21:23:40 +02:00
|
|
|
printSImmOperand<8>(MI, OpNum, O);
|
2013-05-06 18:15:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
2015-05-05 21:23:40 +02:00
|
|
|
printUImmOperand<8>(MI, OpNum, O);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printUImmOperand<12>(MI, OpNum, O);
|
2013-05-06 18:15:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
2015-05-05 21:23:40 +02:00
|
|
|
printSImmOperand<16>(MI, OpNum, O);
|
2013-05-06 18:15:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
2015-05-05 21:23:40 +02:00
|
|
|
printUImmOperand<16>(MI, OpNum, O);
|
2013-05-06 18:15:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
2015-05-05 21:23:40 +02:00
|
|
|
printSImmOperand<32>(MI, OpNum, O);
|
2013-05-06 18:15:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
2015-05-05 21:23:40 +02:00
|
|
|
printUImmOperand<32>(MI, OpNum, O);
|
2013-05-06 18:15:19 +02:00
|
|
|
}
|
|
|
|
|
2016-08-08 17:13:08 +02:00
|
|
|
void SystemZInstPrinter::printU48ImmOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printUImmOperand<48>(MI, OpNum, O);
|
|
|
|
}
|
|
|
|
|
2013-05-14 12:17:52 +02:00
|
|
|
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
|
2015-06-09 02:31:39 +02:00
|
|
|
MO.getExpr()->print(O, &MAI);
|
2013-05-14 12:17:52 +02:00
|
|
|
}
|
|
|
|
|
[MCInstPrinter] Pass `Address` parameter to MCOI::OPERAND_PCREL typed operands. NFC
Follow-up of D72172 and D72180
This patch passes `uint64_t Address` to print methods of PC-relative
operands so that subsequent target specific patches can change
`*InstPrinter::print{Operand,PCRelImm,...}` to customize the output.
Add MCInstPrinter::PrintBranchImmAsAddress which is set to true by
llvm-objdump.
```
// Current llvm-objdump -d output
aarch64: 20000: bl #0
ppc: 20000: bl .+4
x86: 20000: callq 0
// Ideal output
aarch64: 20000: bl 0x20000
ppc: 20000: bl 0x20004
x86: 20000: callq 0x20005
// GNU objdump -d. The lack of 0x is not ideal because the result cannot be re-assembled
aarch64: 20000: bl 20000
ppc: 20000: bl 0x20004
x86: 20000: callq 20005
```
In `lib/Target/X86/X86GenAsmWriter1.inc` (generated by `llvm-tblgen -gen-asm-writer`):
```
case 12:
// CALL64pcrel32, CALLpcrel16, CALLpcrel32, EH_SjLj_Setup, JCXZ, JECXZ, J...
- printPCRelImm(MI, 0, O);
+ printPCRelImm(MI, Address, 0, O);
return;
```
Some targets have 2 `printOperand` overloads, one without `Address` and
one with `Address`. They should annotate derived `Operand` properly with
`let OperandType = "OPERAND_PCREL"`.
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D76574
2020-03-22 20:32:27 +01:00
|
|
|
void SystemZInstPrinter::printPCRelTLSOperand(const MCInst *MI,
|
|
|
|
uint64_t Address, int OpNum,
|
2015-02-18 10:11:36 +01:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-06 18:15:19 +02:00
|
|
|
void SystemZInstPrinter::printOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
2015-06-09 02:31:39 +02:00
|
|
|
printOperand(MI->getOperand(OpNum), &MAI, O);
|
2013-05-06 18:15:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-07-02 16:56:45 +02:00
|
|
|
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 << ')';
|
|
|
|
}
|
|
|
|
|
2016-10-31 15:21:36 +01:00
|
|
|
void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned Base = MI->getOperand(OpNum).getReg();
|
|
|
|
uint64_t Disp = MI->getOperand(OpNum + 1).getImm();
|
|
|
|
unsigned Length = MI->getOperand(OpNum + 2).getReg();
|
|
|
|
O << Disp << "(%" << getRegisterName(Length);
|
|
|
|
if (Base)
|
|
|
|
O << ",%" << getRegisterName(Base);
|
|
|
|
O << ')';
|
|
|
|
}
|
|
|
|
|
2015-05-05 21:23:40 +02:00
|
|
|
void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printAddress(MI->getOperand(OpNum).getReg(),
|
|
|
|
MI->getOperand(OpNum + 1).getImm(),
|
|
|
|
MI->getOperand(OpNum + 2).getReg(), O);
|
|
|
|
}
|
|
|
|
|
2013-05-06 18:15:19 +02:00
|
|
|
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];
|
|
|
|
}
|