]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file contains code to lower ARM MachineInstrs to their corresponding | |
11 | // MCInst records. | |
12 | // | |
13 | //===----------------------------------------------------------------------===// | |
14 | ||
15 | #include "ARM.h" | |
16 | #include "ARMAsmPrinter.h" | |
1a4d82fc | 17 | #include "MCTargetDesc/ARMBaseInfo.h" |
223e47cc | 18 | #include "MCTargetDesc/ARMMCExpr.h" |
223e47cc | 19 | #include "llvm/CodeGen/MachineBasicBlock.h" |
970d7e83 | 20 | #include "llvm/IR/Constants.h" |
1a4d82fc | 21 | #include "llvm/IR/Mangler.h" |
223e47cc LB |
22 | #include "llvm/MC/MCExpr.h" |
23 | #include "llvm/MC/MCInst.h" | |
223e47cc LB |
24 | using namespace llvm; |
25 | ||
26 | ||
27 | MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO, | |
28 | const MCSymbol *Symbol) { | |
29 | const MCExpr *Expr; | |
1a4d82fc JJ |
30 | unsigned Option = MO.getTargetFlags() & ARMII::MO_OPTION_MASK; |
31 | switch (Option) { | |
223e47cc LB |
32 | default: { |
33 | Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, | |
34 | OutContext); | |
1a4d82fc | 35 | switch (Option) { |
223e47cc | 36 | default: llvm_unreachable("Unknown target flag on symbol operand"); |
1a4d82fc | 37 | case ARMII::MO_NO_FLAG: |
223e47cc LB |
38 | break; |
39 | case ARMII::MO_LO16: | |
40 | Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, | |
41 | OutContext); | |
42 | Expr = ARMMCExpr::CreateLower16(Expr, OutContext); | |
43 | break; | |
44 | case ARMII::MO_HI16: | |
45 | Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, | |
46 | OutContext); | |
47 | Expr = ARMMCExpr::CreateUpper16(Expr, OutContext); | |
48 | break; | |
49 | } | |
50 | break; | |
51 | } | |
52 | ||
53 | case ARMII::MO_PLT: | |
1a4d82fc | 54 | Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_PLT, |
223e47cc LB |
55 | OutContext); |
56 | break; | |
57 | } | |
58 | ||
59 | if (!MO.isJTI() && MO.getOffset()) | |
60 | Expr = MCBinaryExpr::CreateAdd(Expr, | |
61 | MCConstantExpr::Create(MO.getOffset(), | |
62 | OutContext), | |
63 | OutContext); | |
64 | return MCOperand::CreateExpr(Expr); | |
65 | ||
66 | } | |
67 | ||
68 | bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO, | |
69 | MCOperand &MCOp) { | |
70 | switch (MO.getType()) { | |
71 | default: llvm_unreachable("unknown operand type"); | |
72 | case MachineOperand::MO_Register: | |
73 | // Ignore all non-CPSR implicit register operands. | |
74 | if (MO.isImplicit() && MO.getReg() != ARM::CPSR) | |
75 | return false; | |
76 | assert(!MO.getSubReg() && "Subregs should be eliminated!"); | |
77 | MCOp = MCOperand::CreateReg(MO.getReg()); | |
78 | break; | |
79 | case MachineOperand::MO_Immediate: | |
80 | MCOp = MCOperand::CreateImm(MO.getImm()); | |
81 | break; | |
82 | case MachineOperand::MO_MachineBasicBlock: | |
83 | MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( | |
84 | MO.getMBB()->getSymbol(), OutContext)); | |
85 | break; | |
1a4d82fc JJ |
86 | case MachineOperand::MO_GlobalAddress: { |
87 | MCOp = GetSymbolRef(MO, | |
88 | GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags())); | |
223e47cc | 89 | break; |
1a4d82fc | 90 | } |
223e47cc LB |
91 | case MachineOperand::MO_ExternalSymbol: |
92 | MCOp = GetSymbolRef(MO, | |
93 | GetExternalSymbolSymbol(MO.getSymbolName())); | |
94 | break; | |
95 | case MachineOperand::MO_JumpTableIndex: | |
96 | MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex())); | |
97 | break; | |
98 | case MachineOperand::MO_ConstantPoolIndex: | |
99 | MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex())); | |
100 | break; | |
101 | case MachineOperand::MO_BlockAddress: | |
102 | MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress())); | |
103 | break; | |
104 | case MachineOperand::MO_FPImmediate: { | |
105 | APFloat Val = MO.getFPImm()->getValueAPF(); | |
106 | bool ignored; | |
107 | Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored); | |
108 | MCOp = MCOperand::CreateFPImm(Val.convertToDouble()); | |
109 | break; | |
110 | } | |
111 | case MachineOperand::MO_RegisterMask: | |
112 | // Ignore call clobbers. | |
113 | return false; | |
114 | } | |
115 | return true; | |
116 | } | |
117 | ||
118 | void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, | |
119 | ARMAsmPrinter &AP) { | |
120 | OutMI.setOpcode(MI->getOpcode()); | |
121 | ||
85aaf69f SL |
122 | // In the MC layer, we keep modified immediates in their encoded form |
123 | bool EncodeImms = false; | |
124 | switch (MI->getOpcode()) { | |
125 | default: break; | |
126 | case ARM::MOVi: | |
127 | case ARM::MVNi: | |
128 | case ARM::CMPri: | |
129 | case ARM::CMNri: | |
130 | case ARM::TSTri: | |
131 | case ARM::TEQri: | |
132 | case ARM::MSRi: | |
133 | case ARM::ADCri: | |
134 | case ARM::ADDri: | |
135 | case ARM::ADDSri: | |
136 | case ARM::SBCri: | |
137 | case ARM::SUBri: | |
138 | case ARM::SUBSri: | |
139 | case ARM::ANDri: | |
140 | case ARM::ORRri: | |
141 | case ARM::EORri: | |
142 | case ARM::BICri: | |
143 | case ARM::RSBri: | |
144 | case ARM::RSBSri: | |
145 | case ARM::RSCri: | |
146 | EncodeImms = true; | |
147 | break; | |
148 | } | |
149 | ||
223e47cc LB |
150 | for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { |
151 | const MachineOperand &MO = MI->getOperand(i); | |
152 | ||
153 | MCOperand MCOp; | |
85aaf69f SL |
154 | if (AP.lowerOperand(MO, MCOp)) { |
155 | if (MCOp.isImm() && EncodeImms) { | |
156 | int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm()); | |
157 | if (Enc != -1) | |
158 | MCOp.setImm(Enc); | |
159 | } | |
223e47cc | 160 | OutMI.addOperand(MCOp); |
85aaf69f | 161 | } |
223e47cc LB |
162 | } |
163 | } |