2009-10-19 19:56:26 +00: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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "asm-printer"
|
2009-10-20 00:42:49 +00:00
|
|
|
#include "ARM.h" // FIXME: FACTOR ENUMS BETTER.
|
2009-10-19 19:56:26 +00:00
|
|
|
#include "ARMInstPrinter.h"
|
2009-10-19 21:21:39 +00:00
|
|
|
#include "ARMAddressingModes.h"
|
2009-10-19 19:56:26 +00:00
|
|
|
#include "llvm/MC/MCInst.h"
|
2009-10-19 21:21:39 +00: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 :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84542 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 21:53:00 +00:00
|
|
|
#include "llvm/MC/MCExpr.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-10-19 19:56:26 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
// Include the auto-generated portion of the assembly writer.
|
|
|
|
#define MachineInstr MCInst
|
|
|
|
#define ARMAsmPrinter ARMInstPrinter // FIXME: REMOVE.
|
|
|
|
#include "ARMGenAsmWriter.inc"
|
|
|
|
#undef MachineInstr
|
|
|
|
#undef ARMAsmPrinter
|
|
|
|
|
2010-03-17 17:52:21 +00:00
|
|
|
static unsigned NextReg(unsigned Reg) {
|
|
|
|
switch (Reg) {
|
2010-03-19 03:18:23 +00:00
|
|
|
default:
|
|
|
|
assert(0 && "Unexpected register enum");
|
|
|
|
|
2010-03-17 17:52:21 +00:00
|
|
|
case ARM::D0:
|
|
|
|
return ARM::D1;
|
|
|
|
case ARM::D1:
|
|
|
|
return ARM::D2;
|
|
|
|
case ARM::D2:
|
|
|
|
return ARM::D3;
|
|
|
|
case ARM::D3:
|
|
|
|
return ARM::D4;
|
|
|
|
case ARM::D4:
|
|
|
|
return ARM::D5;
|
|
|
|
case ARM::D5:
|
|
|
|
return ARM::D6;
|
|
|
|
case ARM::D6:
|
|
|
|
return ARM::D7;
|
|
|
|
case ARM::D7:
|
|
|
|
return ARM::D8;
|
|
|
|
case ARM::D8:
|
|
|
|
return ARM::D9;
|
|
|
|
case ARM::D9:
|
|
|
|
return ARM::D10;
|
|
|
|
case ARM::D10:
|
|
|
|
return ARM::D11;
|
|
|
|
case ARM::D11:
|
|
|
|
return ARM::D12;
|
|
|
|
case ARM::D12:
|
|
|
|
return ARM::D13;
|
|
|
|
case ARM::D13:
|
|
|
|
return ARM::D14;
|
|
|
|
case ARM::D14:
|
|
|
|
return ARM::D15;
|
|
|
|
case ARM::D15:
|
|
|
|
return ARM::D16;
|
|
|
|
case ARM::D16:
|
|
|
|
return ARM::D17;
|
|
|
|
case ARM::D17:
|
|
|
|
return ARM::D18;
|
|
|
|
case ARM::D18:
|
|
|
|
return ARM::D19;
|
|
|
|
case ARM::D19:
|
|
|
|
return ARM::D20;
|
|
|
|
case ARM::D20:
|
|
|
|
return ARM::D21;
|
|
|
|
case ARM::D21:
|
|
|
|
return ARM::D22;
|
|
|
|
case ARM::D22:
|
|
|
|
return ARM::D23;
|
|
|
|
case ARM::D23:
|
|
|
|
return ARM::D24;
|
|
|
|
case ARM::D24:
|
|
|
|
return ARM::D25;
|
|
|
|
case ARM::D25:
|
|
|
|
return ARM::D26;
|
|
|
|
case ARM::D26:
|
|
|
|
return ARM::D27;
|
|
|
|
case ARM::D27:
|
|
|
|
return ARM::D28;
|
|
|
|
case ARM::D28:
|
|
|
|
return ARM::D29;
|
|
|
|
case ARM::D29:
|
|
|
|
return ARM::D30;
|
|
|
|
case ARM::D30:
|
|
|
|
return ARM::D31;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-04 05:04:31 +00:00
|
|
|
void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
// Check for MOVs and print canonical forms, instead.
|
|
|
|
if (MI->getOpcode() == ARM::MOVs) {
|
|
|
|
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()));
|
2010-04-04 04:47:45 +00:00
|
|
|
printSBitModifierOperand(MI, 6, O);
|
|
|
|
printPredicateOperand(MI, 4, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
|
|
|
|
O << '\t' << getRegisterName(Dst.getReg())
|
|
|
|
<< ", " << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
|
|
|
|
return;
|
|
|
|
|
|
|
|
O << ", ";
|
|
|
|
|
|
|
|
if (MO2.getReg()) {
|
|
|
|
O << getRegisterName(MO2.getReg());
|
|
|
|
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
|
|
|
|
} else {
|
|
|
|
O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A8.6.123 PUSH
|
|
|
|
if ((MI->getOpcode() == ARM::STM_UPD || MI->getOpcode() == ARM::t2STM_UPD) &&
|
|
|
|
MI->getOperand(0).getReg() == ARM::SP) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(2);
|
|
|
|
if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
|
|
|
|
O << '\t' << "push";
|
2010-04-04 04:47:45 +00:00
|
|
|
printPredicateOperand(MI, 3, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '\t';
|
2010-04-04 04:47:45 +00:00
|
|
|
printRegisterList(MI, 5, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A8.6.122 POP
|
|
|
|
if ((MI->getOpcode() == ARM::LDM_UPD || MI->getOpcode() == ARM::t2LDM_UPD) &&
|
|
|
|
MI->getOperand(0).getReg() == ARM::SP) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(2);
|
|
|
|
if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
|
|
|
|
O << '\t' << "pop";
|
2010-04-04 04:47:45 +00:00
|
|
|
printPredicateOperand(MI, 3, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '\t';
|
2010-04-04 04:47:45 +00:00
|
|
|
printRegisterList(MI, 5, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A8.6.355 VPUSH
|
|
|
|
if ((MI->getOpcode() == ARM::VSTMS_UPD || MI->getOpcode() ==ARM::VSTMD_UPD) &&
|
|
|
|
MI->getOperand(0).getReg() == ARM::SP) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(2);
|
|
|
|
if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::db) {
|
|
|
|
O << '\t' << "vpush";
|
2010-04-04 04:47:45 +00:00
|
|
|
printPredicateOperand(MI, 3, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '\t';
|
2010-04-04 04:47:45 +00:00
|
|
|
printRegisterList(MI, 5, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A8.6.354 VPOP
|
|
|
|
if ((MI->getOpcode() == ARM::VLDMS_UPD || MI->getOpcode() ==ARM::VLDMD_UPD) &&
|
|
|
|
MI->getOperand(0).getReg() == ARM::SP) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(2);
|
|
|
|
if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::ia) {
|
|
|
|
O << '\t' << "vpop";
|
2010-04-04 04:47:45 +00:00
|
|
|
printPredicateOperand(MI, 3, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '\t';
|
2010-04-04 04:47:45 +00:00
|
|
|
printRegisterList(MI, 5, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
printInstruction(MI, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
}
|
2009-10-19 19:56:26 +00:00
|
|
|
|
2009-10-19 20:59:55 +00:00
|
|
|
void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
2010-04-04 04:47:45 +00:00
|
|
|
raw_ostream &O, const char *Modifier) {
|
2009-10-19 20:59:55 +00:00
|
|
|
const MCOperand &Op = MI->getOperand(OpNo);
|
|
|
|
if (Op.isReg()) {
|
2009-10-20 06:15:28 +00:00
|
|
|
unsigned Reg = Op.getReg();
|
|
|
|
if (Modifier && strcmp(Modifier, "dregpair") == 0) {
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '{' << getRegisterName(Reg) << ", "
|
|
|
|
<< getRegisterName(NextReg(Reg)) << '}';
|
|
|
|
#if 0
|
2009-10-20 06:15:28 +00:00
|
|
|
// FIXME: Breaks e.g. ARM/vmul.ll.
|
|
|
|
assert(0);
|
|
|
|
/*
|
|
|
|
unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0
|
|
|
|
unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1
|
|
|
|
O << '{'
|
|
|
|
<< getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
|
|
|
|
<< '}';*/
|
2010-03-17 17:52:21 +00:00
|
|
|
#endif
|
2009-10-20 06:15:28 +00:00
|
|
|
} else if (Modifier && strcmp(Modifier, "lane") == 0) {
|
|
|
|
assert(0);
|
|
|
|
/*
|
|
|
|
unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
|
|
|
|
unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1,
|
|
|
|
&ARM::DPR_VFP2RegClass);
|
|
|
|
O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
|
|
|
|
*/
|
|
|
|
} else {
|
|
|
|
O << getRegisterName(Reg);
|
|
|
|
}
|
2009-10-19 20:59:55 +00:00
|
|
|
} else if (Op.isImm()) {
|
2010-03-19 03:18:23 +00:00
|
|
|
assert((Modifier && !strcmp(Modifier, "call")) ||
|
2010-03-17 17:52:21 +00:00
|
|
|
((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"));
|
2009-10-19 20:59:55 +00:00
|
|
|
O << '#' << Op.getImm();
|
|
|
|
} else {
|
2009-10-20 06:15:28 +00:00
|
|
|
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
|
2009-10-19 20:59:55 +00:00
|
|
|
assert(Op.isExpr() && "unknown operand kind in printOperand");
|
2010-01-18 00:37:40 +00:00
|
|
|
O << *Op.getExpr();
|
2009-10-19 20:59:55 +00:00
|
|
|
}
|
|
|
|
}
|
2009-10-19 21:21:39 +00:00
|
|
|
|
|
|
|
static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
|
|
|
|
const MCAsmInfo *MAI) {
|
|
|
|
// Break it up into two parts that make up a shifter immediate.
|
Fixed a crasher in arm disassembler within ARMInstPrinter.cpp after calling
ARM_AM::getSoImmVal(V) with a legitimate so_imm value: #245 rotate right by 2.
Introduce ARM_AM::getSOImmValOneOrNoRotate(unsigned Arg) which is called from
ARMInstPrinter.cpp's printSOImm() function, replacing ARM_AM::getSOImmVal(V).
[12:44:43] johnny:/Volumes/data/llvm/git/trunk (local-trunk) $ gdb Debug/bin/llvm-mc
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries ... done
(gdb) set args -triple=arm-apple-darwin9 -debug-only=arm-disassembler --disassemble
(gdb) r
Starting program: /Volumes/data/llvm/git/trunk/Debug/bin/llvm-mc -triple=arm-apple-darwin9 -debug-only=arm-disassembler --disassemble
Reading symbols for shared libraries ++. done
0xf5 0x71 0xf0 0x53
Opcode=201 Name=MVNi Format=ARM_FORMAT_DPFRM(4)
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
-------------------------------------------------------------------------------------------------
| 0: 1: 0: 1| 0: 0: 1: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 1: 1: 1| 0: 0: 0: 1| 1: 1: 1: 1| 0: 1: 0: 1|
-------------------------------------------------------------------------------------------------
mvnpls r7, Assertion failed: (V != -1 && "Not a valid so_imm value!"), function printSOImm, file ARMInstPrinter.cpp, line 229.
Program received signal SIGABRT, Aborted.
0x00007fff88c65886 in __kill ()
(gdb) bt
#0 0x00007fff88c65886 in __kill ()
#1 0x00007fff88d05eae in abort ()
#2 0x00007fff88cf2ef0 in __assert_rtn ()
#3 0x000000010020e422 in printSOImm (O=@0x1010bdf80, V=-1, VerboseAsm=false, MAI=0x1020106d0) at ARMInstPrinter.cpp:229
#4 0x000000010020e5fe in llvm::ARMInstPrinter::printSOImmOperand (this=0x1020107e0, MI=0x7fff5fbfee70, OpNum=1, O=@0x1010bdf80) at ARMInstPrinter.cpp:254
#5 0x00000001001ffbc0 in llvm::ARMInstPrinter::printInstruction (this=0x1020107e0, MI=0x7fff5fbfee70, O=@0x1010bdf80) at ARMGenAsmWriter.inc:3236
#6 0x000000010020c27c in llvm::ARMInstPrinter::printInst (this=0x1020107e0, MI=0x7fff5fbfee70, O=@0x1010bdf80) at ARMInstPrinter.cpp:182
#7 0x000000010003cbff in PrintInsts (DisAsm=@0x10200f4e0, Printer=@0x1020107e0, Bytes=@0x7fff5fbff060, SM=@0x7fff5fbff078) at Disassembler.cpp:65
#8 0x000000010003c8b4 in llvm::Disassembler::disassemble (T=@0x1010c13c0, Triple=@0x1010b6798, Buffer=@0x102010690) at Disassembler.cpp:153
#9 0x000000010004095c in DisassembleInput (ProgName=0x7fff5fbff3f0 "/Volumes/data/llvm/git/trunk/Debug/bin/llvm-mc") at llvm-mc.cpp:347
#10 0x000000010003eefb in main (argc=4, argv=0x7fff5fbff298) at llvm-mc.cpp:374
(gdb) q
The program is running. Exit anyway? (y or n) y
[13:36:26] johnny:/Volumes/data/llvm/git/trunk (local-trunk) $
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101053 91177308-0d34-0410-b5e6-96231b3b80d8
2010-04-12 18:46:53 +00:00
|
|
|
V = ARM_AM::getSOImmValOneOrNoRotate(V);
|
2009-10-19 21:21:39 +00:00
|
|
|
assert(V != -1 && "Not a valid so_imm value!");
|
|
|
|
|
|
|
|
unsigned Imm = ARM_AM::getSOImmValImm(V);
|
|
|
|
unsigned Rot = ARM_AM::getSOImmValRot(V);
|
|
|
|
|
|
|
|
// Print low-level immediate formation info, per
|
|
|
|
// A5.1.3: "Data-processing operands - Immediate".
|
|
|
|
if (Rot) {
|
|
|
|
O << "#" << Imm << ", " << Rot;
|
|
|
|
// Pretty printed version.
|
|
|
|
if (VerboseAsm)
|
|
|
|
O << ' ' << MAI->getCommentString()
|
|
|
|
<< ' ' << (int)ARM_AM::rotr32(Imm, Rot);
|
|
|
|
} else {
|
|
|
|
O << "#" << Imm;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
|
|
|
|
/// immediate in bits 0-7.
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-19 21:21:39 +00:00
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
|
|
|
assert(MO.isImm() && "Not a valid so_imm value!");
|
|
|
|
printSOImm(O, MO.getImm(), VerboseAsm, &MAI);
|
|
|
|
}
|
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 ,
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84543 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 21:57:05 +00:00
|
|
|
|
2009-10-20 00:40:56 +00:00
|
|
|
/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
|
|
|
|
/// followed by an 'orr' to materialize.
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 00:40:56 +00:00
|
|
|
// FIXME: REMOVE this method.
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 00:40:56 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(OpNum+2);
|
|
|
|
|
|
|
|
O << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
// Print the shift opc.
|
|
|
|
O << ", "
|
|
|
|
<< ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
|
|
|
|
<< ' ';
|
|
|
|
|
|
|
|
if (MO2.getReg()) {
|
|
|
|
O << getRegisterName(MO2.getReg());
|
|
|
|
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
|
|
|
|
} else {
|
|
|
|
O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
|
|
|
|
}
|
|
|
|
}
|
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 ,
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84543 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 21:57:05 +00:00
|
|
|
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
|
|
|
|
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 ,
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84543 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 21:57:05 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(Op+1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(Op+2);
|
|
|
|
|
|
|
|
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
2010-04-04 04:47:45 +00:00
|
|
|
printOperand(MI, Op, 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 ,
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84543 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 21:57:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
if (!MO2.getReg()) {
|
2010-03-17 17:52:21 +00:00
|
|
|
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
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 ,
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84543 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 21:57:05 +00:00
|
|
|
O << ", #"
|
2010-03-17 17:52:21 +00:00
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
|
|
|
<< ARM_AM::getAM2Offset(MO3.getImm());
|
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 ,
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84543 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 21:57:05 +00:00
|
|
|
O << "]";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
O << ", "
|
2010-03-17 17:52:21 +00:00
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
|
|
|
<< getRegisterName(MO2.getReg());
|
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 ,
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84543 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 21:57:05 +00:00
|
|
|
|
|
|
|
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
|
|
|
|
O << ", "
|
|
|
|
<< ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
|
|
|
|
<< " #" << ShImm;
|
|
|
|
O << "]";
|
|
|
|
}
|
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84546 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 22:09:23 +00:00
|
|
|
|
2009-10-20 06:15:28 +00:00
|
|
|
void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 06:15:28 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
|
|
|
|
if (!MO1.getReg()) {
|
|
|
|
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
|
|
|
|
assert(ImmOffs && "Malformed indexed load / store!");
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '#'
|
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
|
|
|
<< ImmOffs;
|
2009-10-20 06:15:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-17 17:52:21 +00:00
|
|
|
O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
|
|
|
<< getRegisterName(MO1.getReg());
|
2009-10-20 06:15:28 +00:00
|
|
|
|
|
|
|
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
|
|
|
|
O << ", "
|
|
|
|
<< ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
|
|
|
|
<< " #" << ShImm;
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 06:15:28 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(OpNum+2);
|
|
|
|
|
|
|
|
O << '[' << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
if (MO2.getReg()) {
|
|
|
|
O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
|
|
|
|
<< getRegisterName(MO2.getReg()) << ']';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
|
|
|
|
O << ", #"
|
2010-03-17 17:52:21 +00:00
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
|
|
|
|
<< ImmOffs;
|
2009-10-20 06:15:28 +00:00
|
|
|
O << ']';
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 06:15:28 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
|
|
|
|
if (MO1.getReg()) {
|
|
|
|
O << (char)ARM_AM::getAM3Op(MO2.getImm())
|
|
|
|
<< getRegisterName(MO1.getReg());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
|
|
|
|
assert(ImmOffs && "Malformed indexed load / store!");
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '#'
|
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
|
|
|
|
<< ImmOffs;
|
2009-10-20 06:15:28 +00: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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84546 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 22:09:23 +00:00
|
|
|
|
|
|
|
void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum,
|
2010-04-04 04:47:45 +00:00
|
|
|
raw_ostream &O,
|
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84546 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 22:09:23 +00:00
|
|
|
const char *Modifier) {
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
|
2009-10-19 23:31:43 +00:00
|
|
|
if (Modifier && strcmp(Modifier, "submode") == 0) {
|
2010-03-16 16:19:07 +00:00
|
|
|
O << ARM_AM::getAMSubModeStr(Mode);
|
2009-10-19 23:31:43 +00:00
|
|
|
} else if (Modifier && strcmp(Modifier, "wide") == 0) {
|
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84546 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 22:09:23 +00:00
|
|
|
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
|
|
|
|
if (Mode == ARM_AM::ia)
|
|
|
|
O << ".w";
|
|
|
|
} else {
|
2010-04-04 04:47:45 +00:00
|
|
|
printOperand(MI, OpNum, O);
|
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84546 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 22:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-20 06:15:28 +00:00
|
|
|
void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
|
2010-04-04 04:47:45 +00:00
|
|
|
raw_ostream &O,
|
2009-10-20 06:15:28 +00:00
|
|
|
const char *Modifier) {
|
|
|
|
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.
|
2010-04-04 04:47:45 +00:00
|
|
|
printOperand(MI, OpNum, O);
|
2009-10-20 06:15:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Modifier && strcmp(Modifier, "submode") == 0) {
|
|
|
|
ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
|
2009-11-09 00:11:35 +00:00
|
|
|
O << ARM_AM::getAMSubModeStr(Mode);
|
2009-10-20 06:15:28 +00:00
|
|
|
return;
|
|
|
|
} else if (Modifier && strcmp(Modifier, "base") == 0) {
|
|
|
|
// Used for FSTM{D|S} and LSTM{D|S} operations.
|
|
|
|
O << getRegisterName(MO1.getReg());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
|
|
|
|
O << ", #"
|
2010-03-17 17:52:21 +00:00
|
|
|
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
|
2009-10-20 06:15:28 +00:00
|
|
|
<< ImmOffs*4;
|
|
|
|
}
|
|
|
|
O << "]";
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 06:22:33 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
2010-03-16 23:01:13 +00:00
|
|
|
|
2010-03-20 22:13:40 +00:00
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
if (MO2.getImm()) {
|
|
|
|
// FIXME: Both darwin as and GNU as violate ARM docs here.
|
|
|
|
O << ", :" << MO2.getImm();
|
2009-10-20 06:22:33 +00:00
|
|
|
}
|
2010-03-20 22:13:40 +00:00
|
|
|
O << "]";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-20 22:13:40 +00:00
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
|
|
|
if (MO.getReg() == 0)
|
|
|
|
O << "!";
|
|
|
|
else
|
|
|
|
O << ", " << getRegisterName(MO.getReg());
|
2009-10-20 06:22:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
|
2010-04-04 04:47:45 +00:00
|
|
|
raw_ostream &O,
|
2009-10-20 06:22:33 +00:00
|
|
|
const char *Modifier) {
|
|
|
|
assert(0 && "FIXME: Implement printAddrModePCOperand");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 06:22:33 +00:00
|
|
|
const MCOperand &MO = MI->getOperand(OpNum);
|
|
|
|
uint32_t v = ~MO.getImm();
|
|
|
|
int32_t lsb = CountTrailingZeros_32(v);
|
|
|
|
int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
|
|
|
|
assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
|
|
|
|
O << '#' << lsb << ", #" << width;
|
|
|
|
}
|
2009-10-20 06:15:28 +00:00
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84546 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 22:09:23 +00:00
|
|
|
O << "{";
|
2010-03-17 17:52:21 +00:00
|
|
|
for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
|
|
|
|
if (i != OpNum) O << ", ";
|
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84546 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-19 22:09:23 +00:00
|
|
|
O << getRegisterName(MI->getOperand(i).getReg());
|
|
|
|
}
|
|
|
|
O << "}";
|
|
|
|
}
|
2009-10-19 22:23:04 +00:00
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &Op = MI->getOperand(OpNum);
|
|
|
|
unsigned option = Op.getImm();
|
|
|
|
unsigned mode = option & 31;
|
|
|
|
bool changemode = option >> 5 & 1;
|
|
|
|
unsigned AIF = option >> 6 & 7;
|
|
|
|
unsigned imod = option >> 9 & 3;
|
|
|
|
if (imod == 2)
|
|
|
|
O << "ie";
|
|
|
|
else if (imod == 3)
|
|
|
|
O << "id";
|
|
|
|
O << '\t';
|
|
|
|
if (imod > 1) {
|
|
|
|
if (AIF & 4) O << 'a';
|
|
|
|
if (AIF & 2) O << 'i';
|
|
|
|
if (AIF & 1) O << 'f';
|
|
|
|
if (AIF > 0 && changemode) O << ", ";
|
|
|
|
}
|
|
|
|
if (changemode)
|
|
|
|
O << '#' << mode;
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &Op = MI->getOperand(OpNum);
|
|
|
|
unsigned Mask = Op.getImm();
|
|
|
|
if (Mask) {
|
|
|
|
O << '_';
|
|
|
|
if (Mask & 8) O << 'f';
|
|
|
|
if (Mask & 4) O << 's';
|
|
|
|
if (Mask & 2) O << 'x';
|
|
|
|
if (Mask & 1) O << 'c';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &Op = MI->getOperand(OpNum);
|
|
|
|
O << '#';
|
|
|
|
if (Op.getImm() < 0)
|
|
|
|
O << '-' << (-Op.getImm() - 1);
|
|
|
|
else
|
|
|
|
O << Op.getImm();
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 00:42:49 +00:00
|
|
|
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
|
|
|
|
if (CC != ARMCC::AL)
|
|
|
|
O << ARMCondCodeToString(CC);
|
|
|
|
}
|
|
|
|
|
2010-03-02 17:57:15 +00:00
|
|
|
void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-02 17:57:15 +00:00
|
|
|
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
|
|
|
|
O << ARMCondCodeToString(CC);
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 22:10:05 +00:00
|
|
|
if (MI->getOperand(OpNum).getReg()) {
|
|
|
|
assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
|
|
|
|
"Expect ARM CPSR register!");
|
2009-10-20 00:46:11 +00:00
|
|
|
O << 's';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-19 22:23:04 +00:00
|
|
|
|
2009-10-19 22:33:05 +00:00
|
|
|
void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum,
|
2010-04-04 04:47:45 +00:00
|
|
|
raw_ostream &O,
|
2009-10-19 22:33:05 +00:00
|
|
|
const char *Modifier) {
|
|
|
|
// FIXME: remove this.
|
|
|
|
abort();
|
|
|
|
}
|
2009-10-19 22:23:04 +00:00
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-20 06:15:28 +00:00
|
|
|
O << MI->getOperand(OpNum).getImm();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2009-10-19 22:23:04 +00:00
|
|
|
// FIXME: remove this.
|
|
|
|
abort();
|
|
|
|
}
|
2009-11-19 06:57:41 +00:00
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-01-25 22:13:10 +00:00
|
|
|
O << "#" << MI->getOperand(OpNum).getImm() * 4;
|
2009-11-19 06:57:41 +00:00
|
|
|
}
|
2010-03-17 17:52:21 +00:00
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
// (3 - the number of trailing zeros) is the number of then / else.
|
|
|
|
unsigned Mask = MI->getOperand(OpNum).getImm();
|
|
|
|
unsigned CondBit0 = Mask >> 4 & 1;
|
|
|
|
unsigned NumTZ = CountTrailingZeros_32(Mask);
|
|
|
|
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 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(Op+1);
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
O << ", " << getRegisterName(MO2.getReg()) << "]";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
|
2010-04-04 04:47:45 +00:00
|
|
|
raw_ostream &O,
|
2010-03-17 17:52:21 +00:00
|
|
|
unsigned Scale) {
|
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(Op+1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(Op+2);
|
|
|
|
|
|
|
|
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
2010-04-04 04:47:45 +00:00
|
|
|
printOperand(MI, Op, O);
|
2010-03-17 17:52:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
if (MO3.getReg())
|
|
|
|
O << ", " << getRegisterName(MO3.getReg());
|
|
|
|
else if (unsigned ImmOffs = MO2.getImm())
|
|
|
|
O << ", #" << ImmOffs * Scale;
|
|
|
|
O << "]";
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printThumbAddrModeRI5Operand(MI, Op, O, 1);
|
2010-03-17 17:52:21 +00:00
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printThumbAddrModeRI5Operand(MI, Op, O, 2);
|
2010-03-17 17:52:21 +00:00
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op,
|
|
|
|
raw_ostream &O) {
|
|
|
|
printThumbAddrModeRI5Operand(MI, Op, O, 4);
|
2010-03-17 17:52:21 +00:00
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(Op);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(Op+1);
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
if (unsigned ImmOffs = MO2.getImm())
|
|
|
|
O << ", #" << ImmOffs*4;
|
|
|
|
O << "]";
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
|
|
|
|
if (MI->getOpcode() == ARM::t2TBH)
|
|
|
|
O << ", lsl #1";
|
|
|
|
O << ']';
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
|
|
|
|
unsigned Reg = MO1.getReg();
|
|
|
|
O << getRegisterName(Reg);
|
|
|
|
|
|
|
|
// Print the shift opc.
|
|
|
|
O << ", "
|
|
|
|
<< ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
|
|
|
|
<< " ";
|
|
|
|
|
|
|
|
assert(MO2.isImm() && "Not a valid t2_so_reg value!");
|
|
|
|
O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
unsigned OffImm = MO2.getImm();
|
|
|
|
if (OffImm) // Don't print +0.
|
|
|
|
O << ", #" << OffImm;
|
|
|
|
O << "]";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
int32_t OffImm = (int32_t)MO2.getImm();
|
|
|
|
// Don't print +0.
|
|
|
|
if (OffImm < 0)
|
|
|
|
O << ", #-" << -OffImm;
|
|
|
|
else if (OffImm > 0)
|
|
|
|
O << ", #" << OffImm;
|
|
|
|
O << "]";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
int32_t OffImm = (int32_t)MO2.getImm() / 4;
|
|
|
|
// Don't print +0.
|
|
|
|
if (OffImm < 0)
|
|
|
|
O << ", #-" << -OffImm * 4;
|
|
|
|
else if (OffImm > 0)
|
|
|
|
O << ", #" << OffImm * 4;
|
|
|
|
O << "]";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
int32_t OffImm = (int32_t)MO1.getImm();
|
|
|
|
// Don't print +0.
|
|
|
|
if (OffImm < 0)
|
|
|
|
O << "#-" << -OffImm;
|
|
|
|
else if (OffImm > 0)
|
|
|
|
O << "#" << OffImm;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
int32_t OffImm = (int32_t)MO1.getImm() / 4;
|
|
|
|
// Don't print +0.
|
|
|
|
if (OffImm < 0)
|
|
|
|
O << "#-" << -OffImm * 4;
|
|
|
|
else if (OffImm > 0)
|
|
|
|
O << "#" << OffImm * 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
|
2010-04-04 04:47:45 +00:00
|
|
|
unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
const MCOperand &MO1 = MI->getOperand(OpNum);
|
|
|
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
|
|
|
const MCOperand &MO3 = MI->getOperand(OpNum+2);
|
|
|
|
|
|
|
|
O << "[" << getRegisterName(MO1.getReg());
|
|
|
|
|
|
|
|
assert(MO2.getReg() && "Invalid so_reg load / store address!");
|
|
|
|
O << ", " << getRegisterName(MO2.getReg());
|
|
|
|
|
|
|
|
unsigned ShAmt = MO3.getImm();
|
|
|
|
if (ShAmt) {
|
|
|
|
assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
|
|
|
|
O << ", lsl #" << ShAmt;
|
|
|
|
}
|
|
|
|
O << "]";
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '#' << MI->getOperand(OpNum).getImm();
|
|
|
|
}
|
|
|
|
|
2010-04-04 04:47:45 +00:00
|
|
|
void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
|
|
|
|
raw_ostream &O) {
|
2010-03-17 17:52:21 +00:00
|
|
|
O << '#' << MI->getOperand(OpNum).getImm();
|
|
|
|
}
|
|
|
|
|