2009-10-20 03:56:26 +08:00
|
|
|
//===-- 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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "ARMInstPrinter.h"
|
2017-07-19 20:57:16 +08:00
|
|
|
#include "Utils/ARMBaseInfo.h"
|
|
|
|
#include "ARMBaseRegisterInfo.h"
|
|
|
|
#include "ARMBaseRegisterInfo.h"
|
2011-07-21 07:34:39 +08:00
|
|
|
#include "MCTargetDesc/ARMAddressingModes.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "MCTargetDesc/ARMBaseInfo.h"
|
2009-10-20 05:21:39 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
add jump tables, constant pools and some trivial global
lowering stuff. We can now compile hello world to:
_main:
stm ,
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0,
ldr r0,
bl _printf
ldr r0,
mov sp, r7
ldm ,
Almost looks like arm code :)
llvm-svn: 84542
2009-10-20 05:53:00 +08:00
|
|
|
#include "llvm/MC/MCExpr.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/MC/MCInst.h"
|
2012-04-02 15:01:04 +08:00
|
|
|
#include "llvm/MC/MCInstrInfo.h"
|
2012-03-06 03:33:30 +08:00
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2015-12-26 06:10:01 +08:00
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
2017-02-04 05:48:12 +08:00
|
|
|
#include "llvm/MC/SubtargetFeature.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/MathExtras.h"
|
add jump tables, constant pools and some trivial global
lowering stuff. We can now compile hello world to:
_main:
stm ,
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0,
ldr r0,
bl _printf
ldr r0,
mov sp, r7
ldm ,
Almost looks like arm code :)
llvm-svn: 84542
2009-10-20 05:53:00 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-02-04 05:48:12 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
|
2009-10-20 03:56:26 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:41:26 +08:00
|
|
|
#define DEBUG_TYPE "asm-printer"
|
|
|
|
|
2016-06-03 21:19:43 +08:00
|
|
|
#define PRINT_ALIAS_INSTR
|
2009-10-20 03:56:26 +08:00
|
|
|
#include "ARMGenAsmWriter.inc"
|
|
|
|
|
2011-08-12 02:41:59 +08:00
|
|
|
/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
|
|
|
|
///
|
2011-10-13 00:36:01 +08:00
|
|
|
/// getSORegOffset returns an integer from 0-31, representing '32' as 0.
|
2011-08-12 02:41:59 +08:00
|
|
|
static unsigned translateShiftImm(unsigned imm) {
|
2012-09-22 19:18:12 +08:00
|
|
|
// lsr #32 and asr #32 exist, but should be encoded as a 0.
|
|
|
|
assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
|
|
|
|
|
2011-08-12 02:41:59 +08:00
|
|
|
if (imm == 0)
|
|
|
|
return 32;
|
|
|
|
return imm;
|
|
|
|
}
|
|
|
|
|
2012-09-22 19:18:12 +08:00
|
|
|
/// Prints the shift value with an immediate value.
|
|
|
|
static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc,
|
2015-03-28 07:24:22 +08:00
|
|
|
unsigned ShImm, bool UseMarkup) {
|
2012-09-22 19:18:12 +08:00
|
|
|
if (ShOpc == ARM_AM::no_shift || (ShOpc == ARM_AM::lsl && !ShImm))
|
|
|
|
return;
|
|
|
|
O << ", ";
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
assert(!(ShOpc == ARM_AM::ror && !ShImm) && "Cannot have ror #0");
|
2012-09-22 19:18:12 +08:00
|
|
|
O << getShiftOpcStr(ShOpc);
|
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
if (ShOpc != ARM_AM::rrx) {
|
2012-10-23 06:31:46 +08:00
|
|
|
O << " ";
|
|
|
|
if (UseMarkup)
|
|
|
|
O << "<imm:";
|
|
|
|
O << "#" << translateShiftImm(ShImm);
|
|
|
|
if (UseMarkup)
|
|
|
|
O << ">";
|
|
|
|
}
|
2012-09-22 19:18:12 +08:00
|
|
|
}
|
2011-09-08 01:24:38 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
|
2015-03-31 05:52:28 +08:00
|
|
|
const MCRegisterInfo &MRI)
|
2015-03-28 07:41:42 +08:00
|
|
|
: MCInstPrinter(MAI, MII, MRI) {}
|
2011-09-08 01:24:38 +08:00
|
|
|
|
2011-06-02 10:34:55 +08:00
|
|
|
void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
|
2015-03-28 07:24:22 +08:00
|
|
|
OS << markup("<reg:") << getRegisterName(RegNo) << markup(">");
|
2011-03-06 02:43:32 +08:00
|
|
|
}
|
2010-10-29 05:37:33 +08:00
|
|
|
|
2011-09-16 07:38:46 +08:00
|
|
|
void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
2015-03-28 04:36:02 +08:00
|
|
|
StringRef Annot, const MCSubtargetInfo &STI) {
|
2010-11-13 18:40:19 +08:00
|
|
|
unsigned Opcode = MI->getOpcode();
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
switch (Opcode) {
|
2010-03-18 01:52:21 +08:00
|
|
|
// Check for MOVs and print canonical forms, instead.
|
2013-10-18 22:41:50 +08:00
|
|
|
case ARM::MOVsr: {
|
2010-09-18 06:36:38 +08:00
|
|
|
// FIXME: Thumb variants?
|
2010-03-18 01:52:21 +08:00
|
|
|
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()));
|
2015-03-28 07:41:42 +08:00
|
|
|
printSBitModifierOperand(MI, 6, STI, O);
|
|
|
|
printPredicateOperand(MI, 4, STI, O);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
O << '\t';
|
|
|
|
printRegName(O, Dst.getReg());
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MO1.getReg());
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MO2.getReg());
|
2011-07-22 07:38:37 +08:00
|
|
|
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
|
2011-09-22 01:58:45 +08:00
|
|
|
printAnnotation(O, Annot);
|
2011-07-22 07:38:37 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2013-10-18 22:41:50 +08:00
|
|
|
case ARM::MOVsi: {
|
2011-07-22 07:38:37 +08:00
|
|
|
// FIXME: Thumb variants?
|
|
|
|
const MCOperand &Dst = MI->getOperand(0);
|
|
|
|
const MCOperand &MO1 = MI->getOperand(1);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(2);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2011-07-22 07:38:37 +08:00
|
|
|
O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
|
2015-03-28 07:41:42 +08:00
|
|
|
printSBitModifierOperand(MI, 5, STI, O);
|
|
|
|
printPredicateOperand(MI, 3, STI, O);
|
2011-07-22 07:38:37 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
O << '\t';
|
|
|
|
printRegName(O, Dst.getReg());
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MO1.getReg());
|
2011-07-22 07:38:37 +08:00
|
|
|
|
2011-09-16 02:36:29 +08:00
|
|
|
if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {
|
2011-09-22 01:58:45 +08:00
|
|
|
printAnnotation(O, Annot);
|
2011-07-22 07:38:37 +08:00
|
|
|
return;
|
2011-09-16 02:36:29 +08:00
|
|
|
}
|
2011-07-22 07:38:37 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#"
|
|
|
|
<< translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm())) << markup(">");
|
2011-09-22 01:58:45 +08:00
|
|
|
printAnnotation(O, Annot);
|
2010-03-18 01:52:21 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A8.6.123 PUSH
|
2013-10-18 22:41:50 +08:00
|
|
|
case ARM::STMDB_UPD:
|
|
|
|
case ARM::t2STMDB_UPD:
|
|
|
|
if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
|
|
|
|
// Should only print PUSH if there are at least two registers in the list.
|
|
|
|
O << '\t' << "push";
|
2015-03-28 07:41:42 +08:00
|
|
|
printPredicateOperand(MI, 2, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
if (Opcode == ARM::t2STMDB_UPD)
|
|
|
|
O << ".w";
|
|
|
|
O << '\t';
|
2015-03-28 07:41:42 +08:00
|
|
|
printRegisterList(MI, 4, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
printAnnotation(O, Annot);
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARM::STR_PRE_IMM:
|
|
|
|
if (MI->getOperand(2).getReg() == ARM::SP &&
|
|
|
|
MI->getOperand(3).getImm() == -4) {
|
|
|
|
O << '\t' << "push";
|
2015-03-28 07:41:42 +08:00
|
|
|
printPredicateOperand(MI, 4, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
O << "\t{";
|
|
|
|
printRegName(O, MI->getOperand(1).getReg());
|
|
|
|
O << "}";
|
|
|
|
printAnnotation(O, Annot);
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
break;
|
2010-03-18 01:52:21 +08:00
|
|
|
|
|
|
|
// A8.6.122 POP
|
2013-10-18 22:41:50 +08:00
|
|
|
case ARM::LDMIA_UPD:
|
|
|
|
case ARM::t2LDMIA_UPD:
|
|
|
|
if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
|
|
|
|
// Should only print POP if there are at least two registers in the list.
|
|
|
|
O << '\t' << "pop";
|
2015-03-28 07:41:42 +08:00
|
|
|
printPredicateOperand(MI, 2, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
if (Opcode == ARM::t2LDMIA_UPD)
|
|
|
|
O << ".w";
|
|
|
|
O << '\t';
|
2015-03-28 07:41:42 +08:00
|
|
|
printRegisterList(MI, 4, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
printAnnotation(O, Annot);
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
break;
|
2011-08-12 01:35:48 +08:00
|
|
|
|
2013-10-18 22:41:50 +08:00
|
|
|
case ARM::LDR_POST_IMM:
|
|
|
|
if (MI->getOperand(2).getReg() == ARM::SP &&
|
|
|
|
MI->getOperand(4).getImm() == 4) {
|
|
|
|
O << '\t' << "pop";
|
2015-03-28 07:41:42 +08:00
|
|
|
printPredicateOperand(MI, 5, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
O << "\t{";
|
|
|
|
printRegName(O, MI->getOperand(0).getReg());
|
|
|
|
O << "}";
|
|
|
|
printAnnotation(O, Annot);
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
break;
|
2010-03-18 01:52:21 +08:00
|
|
|
|
|
|
|
// A8.6.355 VPUSH
|
2013-10-18 22:41:50 +08:00
|
|
|
case ARM::VSTMSDB_UPD:
|
|
|
|
case ARM::VSTMDDB_UPD:
|
|
|
|
if (MI->getOperand(0).getReg() == ARM::SP) {
|
|
|
|
O << '\t' << "vpush";
|
2015-03-28 07:41:42 +08:00
|
|
|
printPredicateOperand(MI, 2, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
O << '\t';
|
2015-03-28 07:41:42 +08:00
|
|
|
printRegisterList(MI, 4, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
printAnnotation(O, Annot);
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
break;
|
2010-03-18 01:52:21 +08:00
|
|
|
|
|
|
|
// A8.6.354 VPOP
|
2013-10-18 22:41:50 +08:00
|
|
|
case ARM::VLDMSIA_UPD:
|
|
|
|
case ARM::VLDMDIA_UPD:
|
|
|
|
if (MI->getOperand(0).getReg() == ARM::SP) {
|
|
|
|
O << '\t' << "vpop";
|
2015-03-28 07:41:42 +08:00
|
|
|
printPredicateOperand(MI, 2, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
O << '\t';
|
2015-03-28 07:41:42 +08:00
|
|
|
printRegisterList(MI, 4, STI, O);
|
2013-10-18 22:41:50 +08:00
|
|
|
printAnnotation(O, Annot);
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
break;
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2013-10-18 22:41:50 +08:00
|
|
|
case ARM::tLDMIA: {
|
2011-07-19 07:25:34 +08:00
|
|
|
bool Writeback = true;
|
|
|
|
unsigned BaseReg = MI->getOperand(0).getReg();
|
|
|
|
for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
|
|
|
|
if (MI->getOperand(i).getReg() == BaseReg)
|
|
|
|
Writeback = false;
|
|
|
|
}
|
|
|
|
|
2011-08-24 01:41:15 +08:00
|
|
|
O << "\tldm";
|
2011-07-19 07:25:34 +08:00
|
|
|
|
2015-03-28 07:41:42 +08:00
|
|
|
printPredicateOperand(MI, 1, STI, O);
|
2012-10-23 06:31:46 +08:00
|
|
|
O << '\t';
|
|
|
|
printRegName(O, BaseReg);
|
2015-03-28 07:24:22 +08:00
|
|
|
if (Writeback)
|
|
|
|
O << "!";
|
2011-07-19 07:25:34 +08:00
|
|
|
O << ", ";
|
2015-03-28 07:41:42 +08:00
|
|
|
printRegisterList(MI, 3, STI, O);
|
2011-09-22 01:58:45 +08:00
|
|
|
printAnnotation(O, Annot);
|
2011-07-19 07:25:34 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-17 05:55:34 +08:00
|
|
|
// Combine 2 GPRs from disassember into a GPRPair to match with instr def.
|
|
|
|
// ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
|
|
|
|
// a single GPRPair reg operand is used in the .td file to replace the two
|
|
|
|
// GPRs. However, when decoding them, the two GRPs cannot be automatically
|
|
|
|
// expressed as a GPRPair, so we have to manually merge them.
|
|
|
|
// FIXME: We would really like to be able to tablegen'erate this.
|
2015-03-28 07:24:22 +08:00
|
|
|
case ARM::LDREXD:
|
|
|
|
case ARM::STREXD:
|
|
|
|
case ARM::LDAEXD:
|
|
|
|
case ARM::STLEXD: {
|
|
|
|
const MCRegisterClass &MRC = MRI.getRegClass(ARM::GPRRegClassID);
|
2013-08-28 01:38:16 +08:00
|
|
|
bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD;
|
2012-11-17 05:55:34 +08:00
|
|
|
unsigned Reg = MI->getOperand(isStore ? 1 : 0).getReg();
|
|
|
|
if (MRC.contains(Reg)) {
|
|
|
|
MCInst NewMI;
|
|
|
|
MCOperand NewReg;
|
|
|
|
NewMI.setOpcode(Opcode);
|
|
|
|
|
|
|
|
if (isStore)
|
|
|
|
NewMI.addOperand(MI->getOperand(0));
|
2015-05-14 02:37:00 +08:00
|
|
|
NewReg = MCOperand::createReg(MRI.getMatchingSuperReg(
|
2015-03-28 07:24:22 +08:00
|
|
|
Reg, ARM::gsub_0, &MRI.getRegClass(ARM::GPRPairRegClassID)));
|
2012-11-17 05:55:34 +08:00
|
|
|
NewMI.addOperand(NewReg);
|
|
|
|
|
|
|
|
// Copy the rest operands into NewMI.
|
2015-03-28 07:24:22 +08:00
|
|
|
for (unsigned i = isStore ? 3 : 2; i < MI->getNumOperands(); ++i)
|
2012-11-17 05:55:34 +08:00
|
|
|
NewMI.addOperand(MI->getOperand(i));
|
2015-03-28 07:41:42 +08:00
|
|
|
printInstruction(&NewMI, STI, O);
|
2012-11-17 05:55:34 +08:00
|
|
|
return;
|
|
|
|
}
|
2014-12-01 16:33:28 +08:00
|
|
|
break;
|
2014-12-01 16:39:19 +08:00
|
|
|
}
|
2012-11-17 05:55:34 +08:00
|
|
|
}
|
|
|
|
|
2016-06-03 21:19:43 +08:00
|
|
|
if (!printAliasInstr(MI, STI, O))
|
|
|
|
printInstruction(MI, STI, O);
|
|
|
|
|
2011-09-22 01:58:45 +08:00
|
|
|
printAnnotation(O, Annot);
|
2010-11-13 18:40:19 +08:00
|
|
|
}
|
2009-10-20 03:56:26 +08:00
|
|
|
|
2009-10-20 04:59:55 +08:00
|
|
|
void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI, raw_ostream &O) {
|
2009-10-20 04:59:55 +08:00
|
|
|
const MCOperand &Op = MI->getOperand(OpNo);
|
|
|
|
if (Op.isReg()) {
|
2009-10-20 14:15:28 +08:00
|
|
|
unsigned Reg = Op.getReg();
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, Reg);
|
2009-10-20 04:59:55 +08:00
|
|
|
} else if (Op.isImm()) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << '#' << formatImm(Op.getImm()) << markup(">");
|
2009-10-20 04:59:55 +08:00
|
|
|
} else {
|
|
|
|
assert(Op.isExpr() && "unknown operand kind in printOperand");
|
2014-01-08 11:28:14 +08:00
|
|
|
const MCExpr *Expr = Op.getExpr();
|
|
|
|
switch (Expr->getKind()) {
|
|
|
|
case MCExpr::Binary:
|
2015-06-09 08:31:39 +08:00
|
|
|
O << '#';
|
|
|
|
Expr->print(O, &MAI);
|
2014-01-08 11:28:14 +08:00
|
|
|
break;
|
|
|
|
case MCExpr::Constant: {
|
|
|
|
// If a symbolic branch target was added as a constant expression then
|
|
|
|
// print that address in hex. And only print 32 unsigned bits for the
|
|
|
|
// address.
|
|
|
|
const MCConstantExpr *Constant = cast<MCConstantExpr>(Expr);
|
|
|
|
int64_t TargetAddress;
|
2015-05-30 09:25:56 +08:00
|
|
|
if (!Constant->evaluateAsAbsolute(TargetAddress)) {
|
2015-06-09 08:31:39 +08:00
|
|
|
O << '#';
|
|
|
|
Expr->print(O, &MAI);
|
2014-01-08 11:28:14 +08:00
|
|
|
} else {
|
|
|
|
O << "0x";
|
|
|
|
O.write_hex(static_cast<uint32_t>(TargetAddress));
|
|
|
|
}
|
|
|
|
break;
|
2011-10-05 06:44:48 +08:00
|
|
|
}
|
2014-01-08 11:28:14 +08:00
|
|
|
default:
|
|
|
|
// FIXME: Should we always treat this as if it is a constant literal and
|
|
|
|
// prefix it with '#'?
|
2015-06-09 08:31:39 +08:00
|
|
|
Expr->print(O, &MAI);
|
2014-01-08 11:28:14 +08:00
|
|
|
break;
|
2011-10-05 06:44:48 +08:00
|
|
|
}
|
2009-10-20 04:59:55 +08:00
|
|
|
}
|
|
|
|
}
|
2009-10-20 05:21:39 +08:00
|
|
|
|
2012-10-30 09:04:51 +08:00
|
|
|
void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2012-10-30 09:04:51 +08:00
|
|
|
raw_ostream &O) {
|
2011-09-22 07:44:46 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2013-06-18 16:03:06 +08:00
|
|
|
if (MO1.isExpr()) {
|
2015-06-09 08:31:39 +08:00
|
|
|
MO1.getExpr()->print(O, &MAI);
|
2013-06-18 16:03:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
O << markup("<mem:") << "[pc, ";
|
|
|
|
|
|
|
|
int32_t OffImm = (int32_t)MO1.getImm();
|
|
|
|
bool isSub = OffImm < 0;
|
|
|
|
|
|
|
|
// Special value for #-0. All others are normal.
|
|
|
|
if (OffImm == INT32_MIN)
|
|
|
|
OffImm = 0;
|
|
|
|
if (isSub) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
|
2013-06-18 16:03:06 +08:00
|
|
|
} else {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
|
2012-10-23 06:31:46 +08:00
|
|
|
}
|
2013-06-18 16:03:06 +08:00
|
|
|
O << "]" << markup(">");
|
2011-09-22 07:44:46 +08:00
|
|
|
}
|
|
|
|
|
2009-10-20 08:40:56 +08:00
|
|
|
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
|
|
|
|
// "Addressing Mode 1 - Data-processing operands" forms. This includes:
|
|
|
|
// REG 0 0 - e.g. R5
|
|
|
|
// REG REG 0,SH_OPC - e.g. R5, ROR R3
|
|
|
|
// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
|
2011-07-22 07:38:37 +08:00
|
|
|
void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-20 08:40:56 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(OpNum + 2);
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2009-10-20 08:40:56 +08:00
|
|
|
// Print the shift opc.
|
2010-08-05 08:34:42 +08:00
|
|
|
ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
|
|
|
|
O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
|
2011-07-14 01:50:29 +08:00
|
|
|
if (ShOpc == ARM_AM::rrx)
|
|
|
|
return;
|
2011-10-22 00:56:40 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
O << ' ';
|
|
|
|
printRegName(O, MO2.getReg());
|
2011-07-22 07:38:37 +08:00
|
|
|
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2011-07-22 07:38:37 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2011-07-22 07:38:37 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2011-07-22 07:38:37 +08:00
|
|
|
|
|
|
|
// Print the shift opc.
|
2012-09-22 19:18:19 +08:00
|
|
|
printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
|
2012-10-23 06:31:46 +08:00
|
|
|
ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
|
2009-10-20 08:40:56 +08:00
|
|
|
}
|
add addrmode2 support, getting us up to:
_main:
stm ,
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0, [sp]
ldr r0, LCPI1_0
bl _printf
ldr r0, [sp]
mov sp, r7
ldm ,
llvm-svn: 84543
2009-10-20 05:57:05 +08:00
|
|
|
|
2011-04-05 01:18:19 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Addressing Mode #2
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
|
2011-04-01 07:26:08 +08:00
|
|
|
void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-04-01 07:26:08 +08:00
|
|
|
raw_ostream &O) {
|
add addrmode2 support, getting us up to:
_main:
stm ,
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0, [sp]
ldr r0, LCPI1_0
bl _printf
ldr r0, [sp]
mov sp, r7
ldm ,
llvm-svn: 84543
2009-10-20 05:57:05 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(Op + 1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(Op + 2);
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-09-15 06:27:15 +08:00
|
|
|
|
add addrmode2 support, getting us up to:
_main:
stm ,
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0, [sp]
ldr r0, LCPI1_0
bl _printf
ldr r0, [sp]
mov sp, r7
ldm ,
llvm-svn: 84543
2009-10-20 05:57:05 +08:00
|
|
|
if (!MO2.getReg()) {
|
2012-10-23 06:31:46 +08:00
|
|
|
if (ARM_AM::getAM2Offset(MO3.getImm())) { // Don't print +0.
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#"
|
2012-10-24 06:52:52 +08:00
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
2015-03-28 07:24:22 +08:00
|
|
|
<< ARM_AM::getAM2Offset(MO3.getImm()) << markup(">");
|
2012-10-23 06:31:46 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
add addrmode2 support, getting us up to:
_main:
stm ,
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0, [sp]
ldr r0, LCPI1_0
bl _printf
ldr r0, [sp]
mov sp, r7
ldm ,
llvm-svn: 84543
2009-10-20 05:57:05 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
O << ", ";
|
|
|
|
O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()));
|
|
|
|
printRegName(O, MO2.getReg());
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-09-22 19:18:12 +08:00
|
|
|
printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()),
|
2012-10-23 06:31:46 +08:00
|
|
|
ARM_AM::getAM2Offset(MO3.getImm()), UseMarkup);
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2010-09-15 06:27:15 +08:00
|
|
|
}
|
add register list and hacked up addrmode #4 support, we now get this:
_main:
stmsp! sp!, {r7, lr}
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0, [sp]
ldr r0, LCPI1_0
bl _printf
ldr r0, [sp]
mov sp, r7
ldmsp! sp!, {r7, pc}
Note the unhappy ldm/stm because of modifiers being ignored.
llvm-svn: 84546
2009-10-20 06:09:23 +08:00
|
|
|
|
2011-09-20 06:21:13 +08:00
|
|
|
void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2011-09-20 06:21:13 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(Op + 1);
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MO2.getReg());
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2011-09-20 06:21:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2011-09-20 06:21:13 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(Op + 1);
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MO2.getReg());
|
2012-10-24 06:52:52 +08:00
|
|
|
O << ", lsl " << markup("<imm:") << "#1" << markup(">") << "]" << markup(">");
|
2011-09-20 06:21:13 +08:00
|
|
|
}
|
|
|
|
|
2011-04-01 07:26:08 +08:00
|
|
|
void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-04-01 07:26:08 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
2015-03-28 07:41:42 +08:00
|
|
|
printOperand(MI, Op, STI, O);
|
2011-04-01 07:26:08 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-22 21:12:28 +08:00
|
|
|
#ifndef NDEBUG
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO3 = MI->getOperand(Op + 2);
|
2011-04-01 07:26:08 +08:00
|
|
|
unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
|
2015-03-28 07:24:22 +08:00
|
|
|
assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");
|
2012-09-22 21:12:28 +08:00
|
|
|
#endif
|
2011-04-01 07:26:08 +08:00
|
|
|
|
2015-03-28 07:41:42 +08:00
|
|
|
printAM2PreOrOffsetIndexOp(MI, Op, STI, O);
|
2011-04-01 07:26:08 +08:00
|
|
|
}
|
|
|
|
|
2009-10-20 14:15:28 +08:00
|
|
|
void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
|
2010-04-04 12:47:45 +08:00
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-20 14:15:28 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2009-10-20 14:15:28 +08:00
|
|
|
if (!MO1.getReg()) {
|
|
|
|
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << '#'
|
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) << ImmOffs
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2009-10-20 14:15:28 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()));
|
|
|
|
printRegName(O, MO1.getReg());
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-09-22 19:18:12 +08:00
|
|
|
printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()),
|
2012-10-23 06:31:46 +08:00
|
|
|
ARM_AM::getAM2Offset(MO2.getImm()), UseMarkup);
|
2009-10-20 14:15:28 +08:00
|
|
|
}
|
|
|
|
|
2011-04-05 01:18:19 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// Addressing Mode #3
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
|
2013-04-13 02:47:25 +08:00
|
|
|
raw_ostream &O,
|
|
|
|
bool AlwaysPrintImm0) {
|
2011-04-05 01:18:19 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(Op + 1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(Op + 2);
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << '[';
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2009-10-20 14:15:28 +08:00
|
|
|
if (MO2.getReg()) {
|
2012-10-24 06:52:52 +08:00
|
|
|
O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()));
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO2.getReg());
|
2012-10-24 06:52:52 +08:00
|
|
|
O << ']' << markup(">");
|
2009-10-20 14:15:28 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
// If the op is sub we have to print the immediate even if it is 0
|
2012-05-11 17:10:54 +08:00
|
|
|
unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
|
|
|
|
ARM_AM::AddrOpc op = ARM_AM::getAM3Op(MO3.getImm());
|
2012-09-22 21:12:22 +08:00
|
|
|
|
2013-04-13 02:47:25 +08:00
|
|
|
if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM::sub)) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(op) << ImmOffs
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2012-10-23 06:31:46 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << ']' << markup(">");
|
2009-10-20 14:15:28 +08:00
|
|
|
}
|
|
|
|
|
2013-04-13 02:47:25 +08:00
|
|
|
template <bool AlwaysPrintImm0>
|
2011-04-05 01:18:19 +08:00
|
|
|
void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-04-05 01:18:19 +08:00
|
|
|
raw_ostream &O) {
|
2011-12-20 07:06:24 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
2015-03-28 07:24:22 +08:00
|
|
|
if (!MO1.isReg()) { // For label symbolic references.
|
2015-03-28 07:41:42 +08:00
|
|
|
printOperand(MI, Op, STI, O);
|
2011-12-20 07:06:24 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-07 07:48:04 +08:00
|
|
|
assert(ARM_AM::getAM3IdxMode(MI->getOperand(Op + 2).getImm()) !=
|
|
|
|
ARMII::IndexModePost &&
|
2014-10-07 01:26:36 +08:00
|
|
|
"unexpected idxmode");
|
2013-04-13 02:47:25 +08:00
|
|
|
printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
|
2011-04-05 01:18:19 +08:00
|
|
|
}
|
|
|
|
|
2009-10-20 14:15:28 +08:00
|
|
|
void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
|
2010-04-04 12:47:45 +08:00
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-20 14:15:28 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2009-10-20 14:15:28 +08:00
|
|
|
if (MO1.getReg()) {
|
2012-10-23 06:31:46 +08:00
|
|
|
O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()));
|
|
|
|
printRegName(O, MO1.getReg());
|
2009-10-20 14:15:28 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2009-10-20 14:15:28 +08:00
|
|
|
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << '#'
|
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) << ImmOffs
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2009-10-20 14:15:28 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-08-04 07:50:40 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
|
|
|
unsigned Imm = MO.getImm();
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff)
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2011-08-04 07:50:40 +08:00
|
|
|
}
|
|
|
|
|
2011-08-05 23:48:21 +08:00
|
|
|
void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-08-05 23:48:21 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2011-08-05 23:48:21 +08:00
|
|
|
|
2012-10-23 06:31:46 +08:00
|
|
|
O << (MO2.getImm() ? "" : "-");
|
|
|
|
printRegName(O, MO1.getReg());
|
2011-08-05 23:48:21 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2011-08-05 02:24:14 +08:00
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
|
|
|
unsigned Imm = MO.getImm();
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2)
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2011-08-05 02:24:14 +08:00
|
|
|
}
|
|
|
|
|
2010-11-03 09:01:43 +08:00
|
|
|
void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-11-03 09:11:15 +08:00
|
|
|
raw_ostream &O) {
|
2015-03-28 07:24:22 +08:00
|
|
|
ARM_AM::AMSubMode Mode =
|
|
|
|
ARM_AM::getAM4SubMode(MI->getOperand(OpNum).getImm());
|
2010-11-03 09:01:43 +08:00
|
|
|
O << ARM_AM::getAMSubModeStr(Mode);
|
add register list and hacked up addrmode #4 support, we now get this:
_main:
stmsp! sp!, {r7, lr}
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0, [sp]
ldr r0, LCPI1_0
bl _printf
ldr r0, [sp]
mov sp, r7
ldmsp! sp!, {r7, pc}
Note the unhappy ldm/stm because of modifiers being ignored.
llvm-svn: 84546
2009-10-20 06:09:23 +08:00
|
|
|
}
|
|
|
|
|
2013-04-13 02:47:25 +08:00
|
|
|
template <bool AlwaysPrintImm0>
|
2009-10-20 14:15:28 +08:00
|
|
|
void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-11-03 09:11:15 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-20 14:15:28 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
2015-03-28 07:41:42 +08:00
|
|
|
printOperand(MI, OpNum, STI, O);
|
2009-10-20 14:15:28 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2011-08-30 03:36:44 +08:00
|
|
|
unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
|
2015-03-26 05:33:24 +08:00
|
|
|
ARM_AM::AddrOpc Op = ARM_AM::getAM5Op(MO2.getImm());
|
2013-04-13 02:47:25 +08:00
|
|
|
if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(Op)
|
|
|
|
<< ImmOffs * 4 << markup(">");
|
2009-10-20 14:15:28 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2009-10-20 14:15:28 +08:00
|
|
|
}
|
|
|
|
|
2016-01-25 18:26:26 +08:00
|
|
|
template <bool AlwaysPrintImm0>
|
|
|
|
void ARMInstPrinter::printAddrMode5FP16Operand(const MCInst *MI, unsigned OpNum,
|
|
|
|
const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
|
|
|
|
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
|
|
|
printOperand(MI, OpNum, STI, O);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
O << markup("<mem:") << "[";
|
|
|
|
printRegName(O, MO1.getReg());
|
|
|
|
|
|
|
|
unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());
|
|
|
|
unsigned Op = ARM_AM::getAM5FP16Op(MO2.getImm());
|
|
|
|
if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
|
|
|
|
O << ", "
|
|
|
|
<< markup("<imm:")
|
|
|
|
<< "#"
|
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM5FP16Op(MO2.getImm()))
|
|
|
|
<< ImmOffs * 2
|
|
|
|
<< markup(">");
|
|
|
|
}
|
|
|
|
O << "]" << markup(">");
|
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-20 14:22:33 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2010-09-15 06:27:15 +08:00
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-03-21 06:13:40 +08:00
|
|
|
if (MO2.getImm()) {
|
2013-02-22 18:01:33 +08:00
|
|
|
O << ":" << (MO2.getImm() << 3);
|
2009-10-20 14:22:33 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2010-03-21 06:13:40 +08:00
|
|
|
}
|
|
|
|
|
2011-03-25 05:04:58 +08:00
|
|
|
void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-03-25 05:04:58 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2011-03-25 05:04:58 +08:00
|
|
|
}
|
|
|
|
|
2010-03-21 06:13:40 +08:00
|
|
|
void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
|
2010-04-04 12:47:45 +08:00
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-21 06:13:40 +08:00
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
|
|
|
if (MO.getReg() == 0)
|
|
|
|
O << "!";
|
2012-10-23 06:31:46 +08:00
|
|
|
else {
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MO.getReg());
|
|
|
|
}
|
2009-10-20 14:22:33 +08:00
|
|
|
}
|
|
|
|
|
2010-08-12 07:10:46 +08:00
|
|
|
void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
|
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-08-12 07:10:46 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-20 14:22:33 +08:00
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
|
|
|
uint32_t v = ~MO.getImm();
|
2013-05-25 06:23:49 +08:00
|
|
|
int32_t lsb = countTrailingZeros(v);
|
2015-03-28 07:24:22 +08:00
|
|
|
int32_t width = (32 - countLeadingZeros(v)) - lsb;
|
2009-10-20 14:22:33 +08:00
|
|
|
assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << '#' << lsb << markup(">") << ", " << markup("<imm:")
|
|
|
|
<< '#' << width << markup(">");
|
2009-10-20 14:22:33 +08:00
|
|
|
}
|
2009-10-20 14:15:28 +08:00
|
|
|
|
2010-08-13 04:46:17 +08:00
|
|
|
void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-08-13 04:46:17 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned val = MI->getOperand(OpNum).getImm();
|
2015-05-26 18:47:10 +08:00
|
|
|
O << ARM_MB::MemBOptToString(val, STI.getFeatureBits()[ARM::HasV8Ops]);
|
2010-08-13 04:46:17 +08:00
|
|
|
}
|
|
|
|
|
2013-06-10 22:17:08 +08:00
|
|
|
void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2013-06-10 22:17:08 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned val = MI->getOperand(OpNum).getImm();
|
|
|
|
O << ARM_ISB::InstSyncBOptToString(val);
|
|
|
|
}
|
|
|
|
|
2010-08-17 02:27:34 +08:00
|
|
|
void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-08-12 07:10:46 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned ShiftOp = MI->getOperand(OpNum).getImm();
|
2011-07-26 06:20:28 +08:00
|
|
|
bool isASR = (ShiftOp & (1 << 5)) != 0;
|
|
|
|
unsigned Amt = ShiftOp & 0x1f;
|
2012-10-23 06:31:46 +08:00
|
|
|
if (isASR) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", asr " << markup("<imm:") << "#" << (Amt == 0 ? 32 : Amt)
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2015-03-28 07:24:22 +08:00
|
|
|
} else if (Amt) {
|
|
|
|
O << ", lsl " << markup("<imm:") << "#" << Amt << markup(">");
|
2012-10-23 06:31:46 +08:00
|
|
|
}
|
2010-08-12 07:10:46 +08:00
|
|
|
}
|
|
|
|
|
2011-07-21 05:40:26 +08:00
|
|
|
void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-07-21 05:40:26 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned Imm = MI->getOperand(OpNum).getImm();
|
|
|
|
if (Imm == 0)
|
|
|
|
return;
|
|
|
|
assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
|
2012-10-24 06:52:52 +08:00
|
|
|
O << ", lsl " << markup("<imm:") << "#" << Imm << markup(">");
|
2011-07-21 05:40:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-07-21 05:40:26 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned Imm = MI->getOperand(OpNum).getImm();
|
|
|
|
// A shift amount of 32 is encoded as 0.
|
|
|
|
if (Imm == 0)
|
|
|
|
Imm = 32;
|
|
|
|
assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
|
2012-10-24 06:52:52 +08:00
|
|
|
O << ", asr " << markup("<imm:") << "#" << Imm << markup(">");
|
2011-07-21 05:40:26 +08:00
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
Recommit: ARM: sort register lists by encoding in push/pop instructions.
For example we were producing
push {r8, r10, r11, r4, r5, r7, lr}
This is misleading (r4, r5 and r7 are actually pushed before the rest), and
other components (stack folding recently) often forget to deal with the extra
complexity coming from the different order, leading to miscompiles. Finally, we
warn about our own code in -no-integrated-as mode without this, which is really
not a good idea.
Fixed usage of std::sort so that we (hopefully) use instantiations that
actually exist in GCC 4.8.
llvm-svn: 286881
2016-11-15 04:28:24 +08:00
|
|
|
assert(std::is_sorted(MI->begin() + OpNum, MI->end(),
|
|
|
|
[&](const MCOperand &LHS, const MCOperand &RHS) {
|
|
|
|
return MRI.getEncodingValue(LHS.getReg()) <
|
|
|
|
MRI.getEncodingValue(RHS.getReg());
|
|
|
|
}));
|
|
|
|
|
add register list and hacked up addrmode #4 support, we now get this:
_main:
stmsp! sp!, {r7, lr}
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0, [sp]
ldr r0, LCPI1_0
bl _printf
ldr r0, [sp]
mov sp, r7
ldmsp! sp!, {r7, pc}
Note the unhappy ldm/stm because of modifiers being ignored.
llvm-svn: 84546
2009-10-20 06:09:23 +08:00
|
|
|
O << "{";
|
2015-06-06 02:01:28 +08:00
|
|
|
for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
|
|
|
|
if (i != OpNum)
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", ";
|
2015-06-06 02:01:28 +08:00
|
|
|
printRegName(O, MI->getOperand(i).getReg());
|
add register list and hacked up addrmode #4 support, we now get this:
_main:
stmsp! sp!, {r7, lr}
mov r7, sp
sub sp, sp, #4
mov r0, #0
str r0, [sp]
ldr r0, LCPI1_0
bl _printf
ldr r0, [sp]
mov sp, r7
ldmsp! sp!, {r7, pc}
Note the unhappy ldm/stm because of modifiers being ignored.
llvm-svn: 84546
2009-10-20 06:09:23 +08:00
|
|
|
}
|
|
|
|
O << "}";
|
|
|
|
}
|
2009-10-20 06:23:04 +08:00
|
|
|
|
2012-11-17 05:55:34 +08:00
|
|
|
void ARMInstPrinter::printGPRPairOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2012-11-17 05:55:34 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned Reg = MI->getOperand(OpNum).getReg();
|
|
|
|
printRegName(O, MRI.getSubReg(Reg, ARM::gsub_0));
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MRI.getSubReg(Reg, ARM::gsub_1));
|
|
|
|
}
|
|
|
|
|
2010-10-14 05:00:04 +08:00
|
|
|
void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-10-14 05:00:04 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
const MCOperand &Op = MI->getOperand(OpNum);
|
|
|
|
if (Op.getImm())
|
|
|
|
O << "be";
|
|
|
|
else
|
|
|
|
O << "le";
|
|
|
|
}
|
|
|
|
|
2011-02-14 21:09:44 +08:00
|
|
|
void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI, raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &Op = MI->getOperand(OpNum);
|
2011-02-14 21:09:44 +08:00
|
|
|
O << ARM_PROC::IModToString(Op.getImm());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI, raw_ostream &O) {
|
2011-02-14 21:09:44 +08:00
|
|
|
const MCOperand &Op = MI->getOperand(OpNum);
|
|
|
|
unsigned IFlags = Op.getImm();
|
2015-03-28 07:24:22 +08:00
|
|
|
for (int i = 2; i >= 0; --i)
|
2011-02-14 21:09:44 +08:00
|
|
|
if (IFlags & (1 << i))
|
|
|
|
O << ARM_PROC::IFlagsToString(1 << i);
|
2011-10-06 01:16:40 +08:00
|
|
|
|
|
|
|
if (IFlags == 0)
|
|
|
|
O << "none";
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &Op = MI->getOperand(OpNum);
|
2015-05-26 18:47:10 +08:00
|
|
|
const FeatureBitset &FeatureBits = STI.getFeatureBits();
|
|
|
|
if (FeatureBits[ARM::FeatureMClass]) {
|
2017-07-19 20:57:16 +08:00
|
|
|
|
|
|
|
unsigned SYSm = Op.getImm() & 0xFFF; // 12-bit SYSm
|
2012-05-18 06:18:01 +08:00
|
|
|
unsigned Opcode = MI->getOpcode();
|
2014-09-01 19:25:07 +08:00
|
|
|
|
|
|
|
// For writes, handle extended mask bits if the DSP extension is present.
|
2015-09-25 01:31:16 +08:00
|
|
|
if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSP]) {
|
2017-07-19 20:57:16 +08:00
|
|
|
auto TheReg =ARMSysReg::lookupMClassSysRegBy12bitSYSmValue(SYSm);
|
|
|
|
if (TheReg && TheReg->isInRequiredFeatures({ARM::FeatureDSP})) {
|
|
|
|
O << TheReg->Name;
|
|
|
|
return;
|
2014-09-01 19:25:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle the basic 8-bit mask.
|
|
|
|
SYSm &= 0xff;
|
2015-05-26 18:47:10 +08:00
|
|
|
if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {
|
2014-09-01 19:25:07 +08:00
|
|
|
// ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
|
|
|
|
// alias for MSR APSR_nzcvq.
|
2017-07-19 20:57:16 +08:00
|
|
|
auto TheReg = ARMSysReg::lookupMClassSysRegAPSRNonDeprecated(SYSm);
|
|
|
|
if (TheReg) {
|
|
|
|
O << TheReg->Name;
|
|
|
|
return;
|
2014-09-01 19:25:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-19 20:57:16 +08:00
|
|
|
auto TheReg = ARMSysReg::lookupMClassSysRegBy8bitSYSmValue(SYSm);
|
|
|
|
if (TheReg) {
|
|
|
|
O << TheReg->Name;
|
2016-01-25 19:25:36 +08:00
|
|
|
return;
|
2011-09-28 22:21:38 +08:00
|
|
|
}
|
2017-07-19 20:57:16 +08:00
|
|
|
|
|
|
|
llvm_unreachable("Unexpected mask value!");
|
|
|
|
return;
|
2011-09-28 22:21:38 +08:00
|
|
|
}
|
|
|
|
|
2011-07-20 06:45:10 +08:00
|
|
|
// As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
|
|
|
|
// APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
|
2017-07-19 20:57:16 +08:00
|
|
|
unsigned SpecRegRBit = Op.getImm() >> 4;
|
|
|
|
unsigned Mask = Op.getImm() & 0xf;
|
|
|
|
|
2011-07-20 06:45:10 +08:00
|
|
|
if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
|
|
|
|
O << "APSR_";
|
|
|
|
switch (Mask) {
|
2015-03-28 07:24:22 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Unexpected mask value!");
|
|
|
|
case 4:
|
|
|
|
O << "g";
|
|
|
|
return;
|
|
|
|
case 8:
|
|
|
|
O << "nzcvq";
|
|
|
|
return;
|
|
|
|
case 12:
|
|
|
|
O << "nzcvqg";
|
|
|
|
return;
|
2011-07-20 06:45:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-19 03:45:59 +08:00
|
|
|
if (SpecRegRBit)
|
2011-07-20 06:45:10 +08:00
|
|
|
O << "SPSR";
|
2011-02-19 03:45:59 +08:00
|
|
|
else
|
2011-07-20 06:45:10 +08:00
|
|
|
O << "CPSR";
|
2011-02-19 03:45:59 +08:00
|
|
|
|
2010-03-18 01:52:21 +08:00
|
|
|
if (Mask) {
|
|
|
|
O << '_';
|
2015-03-28 07:24:22 +08:00
|
|
|
if (Mask & 8)
|
|
|
|
O << 'f';
|
|
|
|
if (Mask & 4)
|
|
|
|
O << 's';
|
|
|
|
if (Mask & 2)
|
|
|
|
O << 'x';
|
|
|
|
if (Mask & 1)
|
|
|
|
O << 'c';
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-15 18:47:12 +08:00
|
|
|
void ARMInstPrinter::printBankedRegOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2014-08-15 18:47:12 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
uint32_t Banked = MI->getOperand(OpNum).getImm();
|
2017-08-05 01:10:11 +08:00
|
|
|
auto TheReg = ARMBankedReg::lookupBankedRegByEncoding(Banked);
|
|
|
|
assert(TheReg && "invalid banked register operand");
|
|
|
|
std::string Name = TheReg->Name;
|
2014-08-15 18:47:12 +08:00
|
|
|
|
2017-08-05 01:10:11 +08:00
|
|
|
uint32_t isSPSR = (Banked & 0x20) >> 5;
|
|
|
|
if (isSPSR)
|
|
|
|
Name.replace(0, 4, "SPSR"); // convert 'spsr_' to 'SPSR_'
|
2014-08-15 18:47:12 +08:00
|
|
|
O << Name;
|
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-20 08:42:49 +08:00
|
|
|
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
|
2012-03-02 06:13:02 +08:00
|
|
|
// Handle the undefined 15 CC value here for printing so we don't abort().
|
|
|
|
if ((unsigned)CC == 15)
|
|
|
|
O << "<und>";
|
|
|
|
else if (CC != ARMCC::AL)
|
2009-10-20 08:42:49 +08:00
|
|
|
O << ARMCondCodeToString(CC);
|
|
|
|
}
|
|
|
|
|
2010-09-15 06:27:15 +08:00
|
|
|
void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
|
2010-04-04 12:47:45 +08:00
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-03 01:57:15 +08:00
|
|
|
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
|
|
|
|
O << ARMCondCodeToString(CC);
|
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-21 06:10:05 +08:00
|
|
|
if (MI->getOperand(OpNum).getReg()) {
|
|
|
|
assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
|
|
|
|
"Expect ARM CPSR register!");
|
2009-10-20 08:46:11 +08:00
|
|
|
O << 's';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2009-10-20 14:15:28 +08:00
|
|
|
O << MI->getOperand(OpNum).getImm();
|
|
|
|
}
|
|
|
|
|
2011-01-14 05:46:02 +08:00
|
|
|
void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-10-13 00:34:37 +08:00
|
|
|
raw_ostream &O) {
|
2011-01-14 05:46:02 +08:00
|
|
|
O << "p" << MI->getOperand(OpNum).getImm();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-10-13 00:34:37 +08:00
|
|
|
raw_ostream &O) {
|
2011-01-14 05:46:02 +08:00
|
|
|
O << "c" << MI->getOperand(OpNum).getImm();
|
|
|
|
}
|
|
|
|
|
2011-10-13 01:34:41 +08:00
|
|
|
void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-10-13 01:34:41 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
O << "{" << MI->getOperand(OpNum).getImm() << "}";
|
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI, raw_ostream &O) {
|
2010-09-18 08:04:53 +08:00
|
|
|
llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
|
2009-10-20 06:23:04 +08:00
|
|
|
}
|
2009-11-19 14:57:41 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
template <unsigned scale>
|
2012-08-02 16:13:13 +08:00
|
|
|
void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2012-08-02 16:13:13 +08:00
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
|
|
|
|
|
|
|
if (MO.isExpr()) {
|
2015-06-09 08:31:39 +08:00
|
|
|
MO.getExpr()->print(O, &MAI);
|
2012-08-02 16:13:13 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-07-03 17:21:44 +08:00
|
|
|
int32_t OffImm = (int32_t)MO.getImm() << scale;
|
2012-08-02 16:13:13 +08:00
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<imm:");
|
2012-08-02 16:13:13 +08:00
|
|
|
if (OffImm == INT32_MIN)
|
|
|
|
O << "#-0";
|
|
|
|
else if (OffImm < 0)
|
|
|
|
O << "#-" << -OffImm;
|
|
|
|
else
|
|
|
|
O << "#" << OffImm;
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup(">");
|
2012-08-02 16:13:13 +08:00
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << "#" << formatImm(MI->getOperand(OpNum).getImm() * 4)
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2011-08-18 05:51:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-08-18 05:51:27 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned Imm = MI->getOperand(OpNum).getImm();
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << "#" << formatImm((Imm == 0 ? 32 : Imm))
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2009-11-19 14:57:41 +08:00
|
|
|
}
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
// (3 - the number of trailing zeros) is the number of then / else.
|
|
|
|
unsigned Mask = MI->getOperand(OpNum).getImm();
|
2015-03-28 07:24:22 +08:00
|
|
|
unsigned Firstcond = MI->getOperand(OpNum - 1).getImm();
|
2012-04-27 16:42:59 +08:00
|
|
|
unsigned CondBit0 = Firstcond & 1;
|
2013-05-25 06:23:49 +08:00
|
|
|
unsigned NumTZ = countTrailingZeros(Mask);
|
2010-03-18 01:52:21 +08:00
|
|
|
assert(NumTZ <= 3 && "Invalid IT mask!");
|
|
|
|
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
|
|
|
|
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
|
|
|
if (T)
|
|
|
|
O << 't';
|
|
|
|
else
|
|
|
|
O << 'e';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
2010-12-14 11:36:38 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(Op + 1);
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
2015-03-28 07:41:42 +08:00
|
|
|
printOperand(MI, Op, STI, O);
|
2010-12-14 11:36:38 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
|
|
|
if (unsigned RegNum = MO2.getReg()) {
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, RegNum);
|
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2010-12-14 11:36:38 +08:00
|
|
|
void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
|
2015-03-28 07:41:42 +08:00
|
|
|
unsigned Op,
|
|
|
|
const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O,
|
2010-12-14 11:36:38 +08:00
|
|
|
unsigned Scale) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
2010-12-14 11:36:38 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(Op + 1);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
2015-03-28 07:41:42 +08:00
|
|
|
printOperand(MI, Op, STI, O);
|
2010-03-18 01:52:21 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
|
|
|
if (unsigned ImmOffs = MO2.getImm()) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#" << formatImm(ImmOffs * Scale)
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2012-10-23 06:31:46 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2010-12-14 11:36:38 +08:00
|
|
|
void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
|
|
|
|
unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-12-14 11:36:38 +08:00
|
|
|
raw_ostream &O) {
|
2015-03-28 07:41:42 +08:00
|
|
|
printThumbAddrModeImm5SOperand(MI, Op, STI, O, 1);
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2010-12-14 11:36:38 +08:00
|
|
|
void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
|
|
|
|
unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-12-14 11:36:38 +08:00
|
|
|
raw_ostream &O) {
|
2015-03-28 07:41:42 +08:00
|
|
|
printThumbAddrModeImm5SOperand(MI, Op, STI, O, 2);
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2010-12-14 11:36:38 +08:00
|
|
|
void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
|
|
|
|
unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-12-14 11:36:38 +08:00
|
|
|
raw_ostream &O) {
|
2015-03-28 07:41:42 +08:00
|
|
|
printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2015-03-28 07:41:42 +08:00
|
|
|
printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
|
|
|
|
// register with shift forms.
|
|
|
|
// REG 0 0 - e.g. R5
|
|
|
|
// REG IMM, SH_OPC - e.g. R5, LSL #3
|
2010-04-04 12:47:45 +08:00
|
|
|
void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
|
|
|
unsigned Reg = MO1.getReg();
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, Reg);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
|
|
|
// Print the shift opc.
|
|
|
|
assert(MO2.isImm() && "Not a valid t2_so_reg value!");
|
2012-09-22 19:18:19 +08:00
|
|
|
printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
|
2012-10-23 06:31:46 +08:00
|
|
|
ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2013-04-13 02:47:25 +08:00
|
|
|
template <bool AlwaysPrintImm0>
|
2010-10-26 04:00:01 +08:00
|
|
|
void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-10-26 04:00:01 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
2015-03-28 07:41:42 +08:00
|
|
|
printOperand(MI, OpNum, STI, O);
|
2010-10-27 06:37:02 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2010-10-27 09:19:41 +08:00
|
|
|
int32_t OffImm = (int32_t)MO2.getImm();
|
2010-10-29 02:34:10 +08:00
|
|
|
bool isSub = OffImm < 0;
|
|
|
|
// Special value for #-0. All others are normal.
|
|
|
|
if (OffImm == INT32_MIN)
|
|
|
|
OffImm = 0;
|
2012-10-23 06:31:46 +08:00
|
|
|
if (isSub) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
|
|
|
|
} else if (AlwaysPrintImm0 || OffImm > 0) {
|
|
|
|
O << ", " << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
|
2012-10-23 06:31:46 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
template <bool AlwaysPrintImm0>
|
2010-03-18 01:52:21 +08:00
|
|
|
void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
|
2010-04-04 12:47:45 +08:00
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-03-18 01:52:21 +08:00
|
|
|
|
|
|
|
int32_t OffImm = (int32_t)MO2.getImm();
|
2013-06-18 16:12:51 +08:00
|
|
|
bool isSub = OffImm < 0;
|
2010-03-18 01:52:21 +08:00
|
|
|
// Don't print +0.
|
2011-09-17 05:08:33 +08:00
|
|
|
if (OffImm == INT32_MIN)
|
2013-06-18 16:12:51 +08:00
|
|
|
OffImm = 0;
|
|
|
|
if (isSub) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
|
2013-06-18 16:12:51 +08:00
|
|
|
} else if (AlwaysPrintImm0 || OffImm > 0) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
|
2013-06-18 16:12:51 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
template <bool AlwaysPrintImm0>
|
2010-03-18 01:52:21 +08:00
|
|
|
void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
|
2010-04-04 12:47:45 +08:00
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
if (!MO1.isReg()) { // For label symbolic references.
|
2015-03-28 07:41:42 +08:00
|
|
|
printOperand(MI, OpNum, STI, O);
|
2011-12-20 07:06:24 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2012-08-02 16:29:50 +08:00
|
|
|
int32_t OffImm = (int32_t)MO2.getImm();
|
2013-06-18 16:12:51 +08:00
|
|
|
bool isSub = OffImm < 0;
|
2012-08-02 16:29:50 +08:00
|
|
|
|
|
|
|
assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
|
|
|
|
|
2010-03-18 01:52:21 +08:00
|
|
|
// Don't print +0.
|
2012-08-02 16:29:50 +08:00
|
|
|
if (OffImm == INT32_MIN)
|
2013-06-18 16:12:51 +08:00
|
|
|
OffImm = 0;
|
|
|
|
if (isSub) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
|
2013-06-18 16:12:51 +08:00
|
|
|
} else if (AlwaysPrintImm0 || OffImm > 0) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
|
2013-06-18 16:12:51 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:41:42 +08:00
|
|
|
void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(
|
|
|
|
const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
2011-09-10 02:37:27 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
2011-09-10 02:37:27 +08:00
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
|
|
|
if (MO2.getImm()) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", " << markup("<imm:") << "#" << formatImm(MO2.getImm() * 4)
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2012-10-23 06:31:46 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2011-09-10 02:37:27 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:41:42 +08:00
|
|
|
void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(
|
|
|
|
const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
int32_t OffImm = (int32_t)MO1.getImm();
|
2012-10-24 06:52:52 +08:00
|
|
|
O << ", " << markup("<imm:");
|
2013-06-14 00:40:51 +08:00
|
|
|
if (OffImm == INT32_MIN)
|
|
|
|
O << "#-0";
|
|
|
|
else if (OffImm < 0)
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "#-" << -OffImm;
|
2011-09-24 05:26:40 +08:00
|
|
|
else
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "#" << OffImm;
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:41:42 +08:00
|
|
|
void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(
|
|
|
|
const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2012-08-02 16:29:50 +08:00
|
|
|
int32_t OffImm = (int32_t)MO1.getImm();
|
|
|
|
|
|
|
|
assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
|
|
|
|
|
2013-06-26 21:39:07 +08:00
|
|
|
O << ", " << markup("<imm:");
|
2012-08-02 16:29:50 +08:00
|
|
|
if (OffImm == INT32_MIN)
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "#-0";
|
2012-08-02 16:29:50 +08:00
|
|
|
else if (OffImm < 0)
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "#-" << -OffImm;
|
2013-06-26 21:39:07 +08:00
|
|
|
else
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "#" << OffImm;
|
2013-06-26 21:39:07 +08:00
|
|
|
O << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
|
2010-04-04 12:47:45 +08:00
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-04-04 12:47:45 +08:00
|
|
|
raw_ostream &O) {
|
2010-03-18 01:52:21 +08:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum + 1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(OpNum + 2);
|
2010-03-18 01:52:21 +08:00
|
|
|
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup("<mem:") << "[";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MO1.getReg());
|
2010-03-18 01:52:21 +08:00
|
|
|
|
|
|
|
assert(MO2.getReg() && "Invalid so_reg load / store address!");
|
2012-10-23 06:31:46 +08:00
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MO2.getReg());
|
2010-03-18 01:52:21 +08:00
|
|
|
|
|
|
|
unsigned ShAmt = MO3.getImm();
|
|
|
|
if (ShAmt) {
|
|
|
|
assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
|
2015-03-28 07:24:22 +08:00
|
|
|
O << ", lsl " << markup("<imm:") << "#" << ShAmt << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
2012-10-24 06:52:52 +08:00
|
|
|
O << "]" << markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2011-09-30 08:50:06 +08:00
|
|
|
void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-09-30 08:50:06 +08:00
|
|
|
raw_ostream &O) {
|
2011-01-27 04:57:43 +08:00
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << '#' << ARM_AM::getFPImmFloat(MO.getImm())
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2010-03-18 01:52:21 +08:00
|
|
|
}
|
|
|
|
|
2010-06-12 05:34:50 +08:00
|
|
|
void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2010-06-12 05:34:50 +08:00
|
|
|
raw_ostream &O) {
|
2010-07-13 12:44:34 +08:00
|
|
|
unsigned EncodedImm = MI->getOperand(OpNum).getImm();
|
|
|
|
unsigned EltBits;
|
|
|
|
uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << "#0x";
|
2011-11-08 05:00:59 +08:00
|
|
|
O.write_hex(Val);
|
2012-10-24 06:52:52 +08:00
|
|
|
O << markup(">");
|
2010-04-17 06:40:20 +08:00
|
|
|
}
|
2011-07-23 07:16:18 +08:00
|
|
|
|
2011-07-26 07:09:14 +08:00
|
|
|
void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-07-26 07:09:14 +08:00
|
|
|
raw_ostream &O) {
|
2011-07-23 07:16:18 +08:00
|
|
|
unsigned Imm = MI->getOperand(OpNum).getImm();
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << "#" << formatImm(Imm + 1) << markup(">");
|
2011-07-23 07:16:18 +08:00
|
|
|
}
|
2011-07-27 05:28:43 +08:00
|
|
|
|
|
|
|
void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-07-27 05:28:43 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned Imm = MI->getOperand(OpNum).getImm();
|
|
|
|
if (Imm == 0)
|
|
|
|
return;
|
2015-04-26 01:25:13 +08:00
|
|
|
assert(Imm <= 3 && "illegal ror immediate!");
|
|
|
|
O << ", ror " << markup("<imm:") << "#" << 8 * Imm << markup(">");
|
2011-07-27 05:28:43 +08:00
|
|
|
}
|
2011-10-08 07:56:00 +08:00
|
|
|
|
2014-12-02 18:53:20 +08:00
|
|
|
void ARMInstPrinter::printModImmOperand(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2014-12-02 18:53:20 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
MCOperand Op = MI->getOperand(OpNum);
|
|
|
|
|
|
|
|
// Support for fixups (MCFixup)
|
|
|
|
if (Op.isExpr())
|
2015-03-28 07:41:42 +08:00
|
|
|
return printOperand(MI, OpNum, STI, O);
|
2014-12-02 18:53:20 +08:00
|
|
|
|
|
|
|
unsigned Bits = Op.getImm() & 0xFF;
|
|
|
|
unsigned Rot = (Op.getImm() & 0xF00) >> 7;
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
bool PrintUnsigned = false;
|
|
|
|
switch (MI->getOpcode()) {
|
2014-12-02 18:53:20 +08:00
|
|
|
case ARM::MOVi:
|
|
|
|
// Movs to PC should be treated unsigned
|
|
|
|
PrintUnsigned = (MI->getOperand(OpNum - 1).getReg() == ARM::PC);
|
|
|
|
break;
|
|
|
|
case ARM::MSRi:
|
|
|
|
// Movs to special registers should be treated unsigned
|
|
|
|
PrintUnsigned = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t Rotated = ARM_AM::rotr32(Bits, Rot);
|
|
|
|
if (ARM_AM::getSOImmVal(Rotated) == Op.getImm()) {
|
|
|
|
// #rot has the least possible value
|
|
|
|
O << "#" << markup("<imm:");
|
|
|
|
if (PrintUnsigned)
|
|
|
|
O << static_cast<uint32_t>(Rotated);
|
|
|
|
else
|
|
|
|
O << Rotated;
|
|
|
|
O << markup(">");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Explicit #bits, #rot implied
|
2015-03-28 07:24:22 +08:00
|
|
|
O << "#" << markup("<imm:") << Bits << markup(">") << ", #" << markup("<imm:")
|
|
|
|
<< Rot << markup(">");
|
2014-12-02 18:53:20 +08:00
|
|
|
}
|
|
|
|
|
2011-12-23 06:19:05 +08:00
|
|
|
void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI, raw_ostream &O) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << "#" << 16 - MI->getOperand(OpNum).getImm()
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2011-12-23 06:19:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printFBits32(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI, raw_ostream &O) {
|
2015-03-28 07:24:22 +08:00
|
|
|
O << markup("<imm:") << "#" << 32 - MI->getOperand(OpNum).getImm()
|
2012-10-24 06:52:52 +08:00
|
|
|
<< markup(">");
|
2011-12-23 06:19:05 +08:00
|
|
|
}
|
|
|
|
|
2011-10-08 07:56:00 +08:00
|
|
|
void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-10-08 07:56:00 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
O << "[" << MI->getOperand(OpNum).getImm() << "]";
|
|
|
|
}
|
2011-10-19 07:02:30 +08:00
|
|
|
|
|
|
|
void ARMInstPrinter::printVectorListOne(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-10-19 07:02:30 +08:00
|
|
|
raw_ostream &O) {
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << "}";
|
2011-10-19 07:02:30 +08:00
|
|
|
}
|
2011-10-22 02:54:25 +08:00
|
|
|
|
2012-03-07 06:01:44 +08:00
|
|
|
void ARMInstPrinter::printVectorListTwo(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2012-03-06 03:33:30 +08:00
|
|
|
unsigned Reg = MI->getOperand(OpNum).getReg();
|
|
|
|
unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
|
|
|
|
unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, Reg0);
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, Reg1);
|
|
|
|
O << "}";
|
2012-03-06 03:33:30 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
void ARMInstPrinter::printVectorListTwoSpaced(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2012-03-07 06:01:44 +08:00
|
|
|
raw_ostream &O) {
|
2012-03-06 05:43:40 +08:00
|
|
|
unsigned Reg = MI->getOperand(OpNum).getReg();
|
|
|
|
unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
|
|
|
|
unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, Reg0);
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, Reg1);
|
|
|
|
O << "}";
|
2012-03-06 05:43:40 +08:00
|
|
|
}
|
|
|
|
|
2011-10-22 04:02:19 +08:00
|
|
|
void ARMInstPrinter::printVectorListThree(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-10-22 04:02:19 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
// Normally, it's not safe to use register enum values directly with
|
|
|
|
// addition to get the next register, but for VFP registers, the
|
|
|
|
// sort order is guaranteed because they're all of the form D<n>.
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 1);
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 2);
|
|
|
|
O << "}";
|
2011-10-22 04:02:19 +08:00
|
|
|
}
|
2011-10-22 04:35:01 +08:00
|
|
|
|
|
|
|
void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-10-22 04:35:01 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
// Normally, it's not safe to use register enum values directly with
|
|
|
|
// addition to get the next register, but for VFP registers, the
|
|
|
|
// sort order is guaranteed because they're all of the form D<n>.
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 1);
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 2);
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 3);
|
|
|
|
O << "}";
|
2011-10-22 04:35:01 +08:00
|
|
|
}
|
2011-11-30 09:09:44 +08:00
|
|
|
|
|
|
|
void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,
|
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-11-30 09:09:44 +08:00
|
|
|
raw_ostream &O) {
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << "[]}";
|
2011-11-30 09:09:44 +08:00
|
|
|
}
|
|
|
|
|
2011-12-01 02:21:25 +08:00
|
|
|
void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst *MI,
|
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2011-12-01 02:21:25 +08:00
|
|
|
raw_ostream &O) {
|
2012-03-07 06:01:44 +08:00
|
|
|
unsigned Reg = MI->getOperand(OpNum).getReg();
|
|
|
|
unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
|
|
|
|
unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, Reg0);
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, Reg1);
|
|
|
|
O << "[]}";
|
2011-12-01 02:21:25 +08:00
|
|
|
}
|
2011-12-15 03:35:22 +08:00
|
|
|
|
2012-01-25 07:47:04 +08:00
|
|
|
void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst *MI,
|
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2012-01-25 07:47:04 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
// Normally, it's not safe to use register enum values directly with
|
|
|
|
// addition to get the next register, but for VFP registers, the
|
|
|
|
// sort order is guaranteed because they're all of the form D<n>.
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 1);
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 2);
|
|
|
|
O << "[]}";
|
2012-01-25 07:47:04 +08:00
|
|
|
}
|
|
|
|
|
2012-01-25 08:01:08 +08:00
|
|
|
void ARMInstPrinter::printVectorListFourAllLanes(const MCInst *MI,
|
2015-03-28 07:24:22 +08:00
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2012-01-25 08:01:08 +08:00
|
|
|
// Normally, it's not safe to use register enum values directly with
|
|
|
|
// addition to get the next register, but for VFP registers, the
|
|
|
|
// sort order is guaranteed because they're all of the form D<n>.
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 1);
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 2);
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 3);
|
|
|
|
O << "[]}";
|
2012-01-25 08:01:08 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:41:42 +08:00
|
|
|
void ARMInstPrinter::printVectorListTwoSpacedAllLanes(
|
|
|
|
const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
2012-03-07 07:10:38 +08:00
|
|
|
unsigned Reg = MI->getOperand(OpNum).getReg();
|
|
|
|
unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
|
|
|
|
unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, Reg0);
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, Reg1);
|
|
|
|
O << "[]}";
|
2011-12-21 08:38:54 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:41:42 +08:00
|
|
|
void ARMInstPrinter::printVectorListThreeSpacedAllLanes(
|
|
|
|
const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
2012-01-25 07:47:04 +08:00
|
|
|
// Normally, it's not safe to use register enum values directly with
|
|
|
|
// addition to get the next register, but for VFP registers, the
|
|
|
|
// sort order is guaranteed because they're all of the form D<n>.
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
2015-03-28 07:24:22 +08:00
|
|
|
O << "[], ";
|
2012-10-23 06:31:46 +08:00
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 2);
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 4);
|
|
|
|
O << "[]}";
|
2012-01-25 08:01:08 +08:00
|
|
|
}
|
|
|
|
|
2015-03-28 07:41:42 +08:00
|
|
|
void ARMInstPrinter::printVectorListFourSpacedAllLanes(
|
|
|
|
const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
2012-01-25 08:01:08 +08:00
|
|
|
// Normally, it's not safe to use register enum values directly with
|
|
|
|
// addition to get the next register, but for VFP registers, the
|
|
|
|
// sort order is guaranteed because they're all of the form D<n>.
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 2);
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 4);
|
|
|
|
O << "[], ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 6);
|
|
|
|
O << "[]}";
|
2012-01-25 07:47:04 +08:00
|
|
|
}
|
|
|
|
|
2012-01-24 07:20:46 +08:00
|
|
|
void ARMInstPrinter::printVectorListThreeSpaced(const MCInst *MI,
|
|
|
|
unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2012-01-24 07:20:46 +08:00
|
|
|
raw_ostream &O) {
|
|
|
|
// Normally, it's not safe to use register enum values directly with
|
|
|
|
// addition to get the next register, but for VFP registers, the
|
|
|
|
// sort order is guaranteed because they're all of the form D<n>.
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 2);
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 4);
|
|
|
|
O << "}";
|
2012-01-24 07:20:46 +08:00
|
|
|
}
|
2012-01-24 08:43:17 +08:00
|
|
|
|
2015-03-28 07:24:22 +08:00
|
|
|
void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
|
2015-03-28 07:41:42 +08:00
|
|
|
const MCSubtargetInfo &STI,
|
2015-03-28 07:24:22 +08:00
|
|
|
raw_ostream &O) {
|
2012-01-24 08:43:17 +08:00
|
|
|
// Normally, it's not safe to use register enum values directly with
|
|
|
|
// addition to get the next register, but for VFP registers, the
|
|
|
|
// sort order is guaranteed because they're all of the form D<n>.
|
2012-10-23 06:31:46 +08:00
|
|
|
O << "{";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg());
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 2);
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 4);
|
|
|
|
O << ", ";
|
|
|
|
printRegName(O, MI->getOperand(OpNum).getReg() + 6);
|
|
|
|
O << "}";
|
2012-01-24 08:43:17 +08:00
|
|
|
}
|
2017-09-29 21:11:33 +08:00
|
|
|
|
|
|
|
template<int64_t Angle, int64_t Remainder>
|
|
|
|
void ARMInstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
|
|
|
|
const MCSubtargetInfo &STI,
|
|
|
|
raw_ostream &O) {
|
|
|
|
unsigned Val = MI->getOperand(OpNo).getImm();
|
|
|
|
O << "#" << (Val * Angle) + Remainder;
|
|
|
|
}
|
|
|
|
|