/src/keystone/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
Line | Count | Source |
1 | | //===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===// |
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 implements the MipsMCCodeEmitter class. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | // |
14 | | |
15 | | #include "MipsMCCodeEmitter.h" |
16 | | #include "MCTargetDesc/MipsFixupKinds.h" |
17 | | #include "MCTargetDesc/MipsMCExpr.h" |
18 | | #include "MCTargetDesc/MipsMCTargetDesc.h" |
19 | | #include "llvm/ADT/APFloat.h" |
20 | | #include "llvm/ADT/SmallVector.h" |
21 | | #include "llvm/MC/MCContext.h" |
22 | | #include "llvm/MC/MCExpr.h" |
23 | | #include "llvm/MC/MCFixup.h" |
24 | | #include "llvm/MC/MCInst.h" |
25 | | #include "llvm/MC/MCInstrInfo.h" |
26 | | #include "llvm/MC/MCRegisterInfo.h" |
27 | | #include "llvm/MC/MCSubtargetInfo.h" |
28 | | #include "llvm/Support/raw_ostream.h" |
29 | | |
30 | | #define DEBUG_TYPE "mccodeemitter" |
31 | | |
32 | | #define GET_INSTRMAP_INFO |
33 | | #include "MipsGenInstrInfo.inc" |
34 | | #undef GET_INSTRMAP_INFO |
35 | | |
36 | | namespace llvm_ks { |
37 | | MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, |
38 | | const MCRegisterInfo &MRI, |
39 | 761 | MCContext &Ctx) { |
40 | 761 | return new MipsMCCodeEmitter(MCII, Ctx, false); |
41 | 761 | } |
42 | | |
43 | | MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, |
44 | | const MCRegisterInfo &MRI, |
45 | 5.01k | MCContext &Ctx) { |
46 | 5.01k | return new MipsMCCodeEmitter(MCII, Ctx, true); |
47 | 5.01k | } |
48 | | } // End of namespace llvm_ks. |
49 | | |
50 | | // If the D<shift> instruction has a shift amount that is greater |
51 | | // than 31 (checked in calling routine), lower it to a D<shift>32 instruction |
52 | 579 | static void LowerLargeShift(MCInst& Inst) { |
53 | | |
54 | 579 | assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!"); |
55 | 579 | assert(Inst.getOperand(2).isImm()); |
56 | | |
57 | 579 | int64_t Shift = Inst.getOperand(2).getImm(); |
58 | 579 | if (Shift <= 31) |
59 | 491 | return; // Do nothing |
60 | 88 | Shift -= 32; |
61 | | |
62 | | // saminus32 |
63 | 88 | Inst.getOperand(2).setImm(Shift); |
64 | | |
65 | 88 | switch (Inst.getOpcode()) { |
66 | 0 | default: |
67 | | // Calling function is not synchronized |
68 | 0 | llvm_unreachable("Unexpected shift instruction"); |
69 | 88 | case Mips::DSLL: |
70 | 88 | Inst.setOpcode(Mips::DSLL32); |
71 | 88 | return; |
72 | 0 | case Mips::DSRL: |
73 | 0 | Inst.setOpcode(Mips::DSRL32); |
74 | 0 | return; |
75 | 0 | case Mips::DSRA: |
76 | 0 | Inst.setOpcode(Mips::DSRA32); |
77 | 0 | return; |
78 | 0 | case Mips::DROTR: |
79 | 0 | Inst.setOpcode(Mips::DROTR32); |
80 | 0 | return; |
81 | 88 | } |
82 | 88 | } |
83 | | |
84 | | // Pick a DEXT or DINS instruction variant based on the pos and size operands |
85 | 0 | static void LowerDextDins(MCInst& InstIn) { |
86 | 0 | int Opcode = InstIn.getOpcode(); |
87 | |
|
88 | 0 | if (Opcode == Mips::DEXT) |
89 | 0 | assert(InstIn.getNumOperands() == 4 && |
90 | 0 | "Invalid no. of machine operands for DEXT!"); |
91 | 0 | else // Only DEXT and DINS are possible |
92 | 0 | assert(InstIn.getNumOperands() == 5 && |
93 | 0 | "Invalid no. of machine operands for DINS!"); |
94 | | |
95 | 0 | assert(InstIn.getOperand(2).isImm()); |
96 | 0 | int64_t pos = InstIn.getOperand(2).getImm(); |
97 | 0 | assert(InstIn.getOperand(3).isImm()); |
98 | 0 | int64_t size = InstIn.getOperand(3).getImm(); |
99 | |
|
100 | 0 | if (size <= 32) { |
101 | 0 | if (pos < 32) // DEXT/DINS, do nothing |
102 | 0 | return; |
103 | | // DEXTU/DINSU |
104 | 0 | InstIn.getOperand(2).setImm(pos - 32); |
105 | 0 | InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU); |
106 | 0 | return; |
107 | 0 | } |
108 | | // DEXTM/DINSM |
109 | 0 | assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32"); |
110 | 0 | InstIn.getOperand(3).setImm(size - 32); |
111 | 0 | InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM); |
112 | 0 | return; |
113 | 0 | } |
114 | | |
115 | 41.8k | bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { |
116 | 41.8k | return STI.getFeatureBits()[Mips::FeatureMicroMips]; |
117 | 41.8k | } |
118 | | |
119 | 0 | bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const { |
120 | 0 | return STI.getFeatureBits()[Mips::FeatureMips32r6]; |
121 | 0 | } |
122 | | |
123 | 95.9k | void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { |
124 | 95.9k | OS << (char)C; |
125 | 95.9k | } |
126 | | |
127 | | void MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, |
128 | | const MCSubtargetInfo &STI, |
129 | 23.9k | raw_ostream &OS) const { |
130 | | // Output the instruction encoding in little endian byte order. |
131 | | // Little-endian byte ordering: |
132 | | // mips32r2: 4 | 3 | 2 | 1 |
133 | | // microMIPS: 2 | 1 | 4 | 3 |
134 | 23.9k | if (IsLittleEndian && Size == 4 && isMicroMips(STI)) { |
135 | 0 | EmitInstruction(Val >> 16, 2, STI, OS); |
136 | 0 | EmitInstruction(Val, 2, STI, OS); |
137 | 23.9k | } else { |
138 | 119k | for (unsigned i = 0; i < Size; ++i) { |
139 | 95.9k | unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; |
140 | 95.9k | EmitByte((Val >> Shift) & 0xff, OS); |
141 | 95.9k | } |
142 | 23.9k | } |
143 | 23.9k | } |
144 | | |
145 | | /// encodeInstruction - Emit the instruction. |
146 | | /// Size the instruction with Desc.getSize(). |
147 | | void MipsMCCodeEmitter:: |
148 | | encodeInstruction(MCInst &MI, raw_ostream &OS, |
149 | | SmallVectorImpl<MCFixup> &Fixups, |
150 | | const MCSubtargetInfo &STI, |
151 | | unsigned int &KsError) const |
152 | 23.9k | { |
153 | 23.9k | KsError = 0; |
154 | | // Non-pseudo instructions that get changed for direct object |
155 | | // only based on operand values. |
156 | | // If this list of instructions get much longer we will move |
157 | | // the check to a function call. Until then, this is more efficient. |
158 | 23.9k | MCInst TmpInst = MI; |
159 | 23.9k | switch (MI.getOpcode()) { |
160 | | // If shift amount is >= 32 it the inst needs to be lowered further |
161 | 579 | case Mips::DSLL: |
162 | 579 | case Mips::DSRL: |
163 | 579 | case Mips::DSRA: |
164 | 579 | case Mips::DROTR: |
165 | 579 | LowerLargeShift(TmpInst); |
166 | 579 | break; |
167 | | // Double extract instruction is chosen by pos and size operands |
168 | 0 | case Mips::DEXT: |
169 | 0 | case Mips::DINS: |
170 | 0 | LowerDextDins(TmpInst); |
171 | 23.9k | } |
172 | | |
173 | 23.9k | unsigned long N = Fixups.size(); |
174 | 23.9k | uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); |
175 | | |
176 | | // Check for unimplemented opcodes. |
177 | | // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 |
178 | | // so we have to special check for them. |
179 | 23.9k | unsigned Opcode = TmpInst.getOpcode(); |
180 | 23.9k | if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && |
181 | 14.3k | (Opcode != Mips::SLL_MM) && !Binary) |
182 | 0 | llvm_unreachable("unimplemented opcode in encodeInstruction()"); |
183 | | |
184 | 23.9k | int NewOpcode = -1; |
185 | 23.9k | if (isMicroMips(STI)) { |
186 | 0 | if (isMips32r6(STI)) { |
187 | 0 | NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6); |
188 | 0 | if (NewOpcode == -1) |
189 | 0 | NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6); |
190 | 0 | } |
191 | 0 | else |
192 | 0 | NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips); |
193 | | |
194 | | // Check whether it is Dsp instruction. |
195 | 0 | if (NewOpcode == -1) |
196 | 0 | NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp); |
197 | |
|
198 | 0 | if (NewOpcode != -1) { |
199 | 0 | if (Fixups.size() > N) |
200 | 0 | Fixups.pop_back(); |
201 | |
|
202 | 0 | Opcode = NewOpcode; |
203 | 0 | TmpInst.setOpcode (NewOpcode); |
204 | 0 | Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); |
205 | 0 | } |
206 | 0 | } |
207 | | |
208 | 23.9k | const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); |
209 | | |
210 | | // Get byte count of instruction |
211 | 23.9k | unsigned Size = Desc.getSize(); |
212 | 23.9k | if (!Size) |
213 | 0 | llvm_unreachable("Desc.getSize() returns 0"); |
214 | | |
215 | 23.9k | EmitInstruction(Binary, Size, STI, OS); |
216 | | |
217 | | // Keystone: update Inst.Address to point to the next instruction |
218 | 23.9k | MI.setAddress(MI.getAddress() + Size); |
219 | 23.9k | } |
220 | | |
221 | | /// getBranchTargetOpValue - Return binary encoding of the branch |
222 | | /// target operand. If the machine operand requires relocation, |
223 | | /// record the relocation and return zero. |
224 | | unsigned MipsMCCodeEmitter:: |
225 | | getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, |
226 | | SmallVectorImpl<MCFixup> &Fixups, |
227 | 6.35k | const MCSubtargetInfo &STI) const { |
228 | | |
229 | 6.35k | const MCOperand &MO = MI.getOperand(OpNo); |
230 | | |
231 | | // If the destination is an immediate, divide by 4. |
232 | 6.35k | if (MO.isImm()) return (MO.getImm() - MI.getAddress() - 4) >> 2; |
233 | | |
234 | 6.35k | assert(MO.isExpr() && |
235 | 6.25k | "getBranchTargetOpValue expects only expressions or immediates"); |
236 | | |
237 | 6.25k | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
238 | 6.25k | MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); |
239 | 6.25k | Fixups.push_back(MCFixup::create(0, FixupExpression, |
240 | 6.25k | MCFixupKind(Mips::fixup_Mips_PC16))); |
241 | 6.25k | return 0; |
242 | 6.25k | } |
243 | | |
244 | | /// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch |
245 | | /// target operand. If the machine operand requires relocation, |
246 | | /// record the relocation and return zero. |
247 | | unsigned MipsMCCodeEmitter:: |
248 | | getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, |
249 | | SmallVectorImpl<MCFixup> &Fixups, |
250 | 0 | const MCSubtargetInfo &STI) const { |
251 | |
|
252 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
253 | | |
254 | | // If the destination is an immediate, divide by 2. |
255 | 0 | if (MO.isImm()) return MO.getImm() >> 1; |
256 | | |
257 | 0 | assert(MO.isExpr() && |
258 | 0 | "getBranchTargetOpValueMM expects only expressions or immediates"); |
259 | | |
260 | 0 | const MCExpr *Expr = MO.getExpr(); |
261 | 0 | Fixups.push_back(MCFixup::create(0, Expr, |
262 | 0 | MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1))); |
263 | 0 | return 0; |
264 | 0 | } |
265 | | |
266 | | /// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS |
267 | | /// 10-bit branch target operand. If the machine operand requires relocation, |
268 | | /// record the relocation and return zero. |
269 | | unsigned MipsMCCodeEmitter:: |
270 | | getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, |
271 | | SmallVectorImpl<MCFixup> &Fixups, |
272 | 0 | const MCSubtargetInfo &STI) const { |
273 | |
|
274 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
275 | | |
276 | | // If the destination is an immediate, divide by 2. |
277 | 0 | if (MO.isImm()) return MO.getImm() >> 1; |
278 | | |
279 | 0 | assert(MO.isExpr() && |
280 | 0 | "getBranchTargetOpValuePC10 expects only expressions or immediates"); |
281 | | |
282 | 0 | const MCExpr *Expr = MO.getExpr(); |
283 | 0 | Fixups.push_back(MCFixup::create(0, Expr, |
284 | 0 | MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1))); |
285 | 0 | return 0; |
286 | 0 | } |
287 | | |
288 | | /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch |
289 | | /// target operand. If the machine operand requires relocation, |
290 | | /// record the relocation and return zero. |
291 | | unsigned MipsMCCodeEmitter:: |
292 | | getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, |
293 | | SmallVectorImpl<MCFixup> &Fixups, |
294 | 0 | const MCSubtargetInfo &STI) const { |
295 | |
|
296 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
297 | | |
298 | | // If the destination is an immediate, divide by 2. |
299 | 0 | if (MO.isImm()) return MO.getImm() >> 1; |
300 | | |
301 | 0 | assert(MO.isExpr() && |
302 | 0 | "getBranchTargetOpValueMM expects only expressions or immediates"); |
303 | | |
304 | 0 | const MCExpr *Expr = MO.getExpr(); |
305 | 0 | Fixups.push_back(MCFixup::create(0, Expr, |
306 | 0 | MCFixupKind(Mips:: |
307 | 0 | fixup_MICROMIPS_PC16_S1))); |
308 | 0 | return 0; |
309 | 0 | } |
310 | | |
311 | | /// getBranchTarget21OpValue - Return binary encoding of the branch |
312 | | /// target operand. If the machine operand requires relocation, |
313 | | /// record the relocation and return zero. |
314 | | unsigned MipsMCCodeEmitter:: |
315 | | getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, |
316 | | SmallVectorImpl<MCFixup> &Fixups, |
317 | 0 | const MCSubtargetInfo &STI) const { |
318 | |
|
319 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
320 | | |
321 | | // If the destination is an immediate, divide by 4. |
322 | 0 | if (MO.isImm()) return MO.getImm() >> 2; |
323 | | |
324 | 0 | assert(MO.isExpr() && |
325 | 0 | "getBranchTarget21OpValue expects only expressions or immediates"); |
326 | | |
327 | 0 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
328 | 0 | MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); |
329 | 0 | Fixups.push_back(MCFixup::create(0, FixupExpression, |
330 | 0 | MCFixupKind(Mips::fixup_MIPS_PC21_S2))); |
331 | 0 | return 0; |
332 | 0 | } |
333 | | |
334 | | /// getBranchTarget26OpValue - Return binary encoding of the branch |
335 | | /// target operand. If the machine operand requires relocation, |
336 | | /// record the relocation and return zero. |
337 | | unsigned MipsMCCodeEmitter:: |
338 | | getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, |
339 | | SmallVectorImpl<MCFixup> &Fixups, |
340 | 13 | const MCSubtargetInfo &STI) const { |
341 | | |
342 | 13 | const MCOperand &MO = MI.getOperand(OpNo); |
343 | | |
344 | | // If the destination is an immediate, divide by 4. |
345 | 13 | if (MO.isImm()) return MO.getImm() >> 2; |
346 | | |
347 | 13 | assert(MO.isExpr() && |
348 | 9 | "getBranchTarget26OpValue expects only expressions or immediates"); |
349 | | |
350 | 9 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
351 | 9 | MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); |
352 | 9 | Fixups.push_back(MCFixup::create(0, FixupExpression, |
353 | 9 | MCFixupKind(Mips::fixup_MIPS_PC26_S2))); |
354 | 9 | return 0; |
355 | 9 | } |
356 | | |
357 | | /// getBranchTarget26OpValueMM - Return binary encoding of the branch |
358 | | /// target operand. If the machine operand requires relocation, |
359 | | /// record the relocation and return zero. |
360 | | unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM( |
361 | | const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, |
362 | 0 | const MCSubtargetInfo &STI) const { |
363 | |
|
364 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
365 | | |
366 | | // If the destination is an immediate, divide by 2. |
367 | 0 | if (MO.isImm()) |
368 | 0 | return MO.getImm() >> 1; |
369 | | |
370 | | // TODO: Push 26 PC fixup. |
371 | 0 | return 0; |
372 | 0 | } |
373 | | |
374 | | /// getJumpOffset16OpValue - Return binary encoding of the jump |
375 | | /// target operand. If the machine operand requires relocation, |
376 | | /// record the relocation and return zero. |
377 | | unsigned MipsMCCodeEmitter:: |
378 | | getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo, |
379 | | SmallVectorImpl<MCFixup> &Fixups, |
380 | 0 | const MCSubtargetInfo &STI) const { |
381 | |
|
382 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
383 | |
|
384 | 0 | if (MO.isImm()) return MO.getImm(); |
385 | | |
386 | 0 | assert(MO.isExpr() && |
387 | 0 | "getJumpOffset16OpValue expects only expressions or an immediate"); |
388 | | |
389 | | // TODO: Push fixup. |
390 | 0 | return 0; |
391 | 0 | } |
392 | | |
393 | | /// getJumpTargetOpValue - Return binary encoding of the jump |
394 | | /// target operand. If the machine operand requires relocation, |
395 | | /// record the relocation and return zero. |
396 | | unsigned MipsMCCodeEmitter:: |
397 | | getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, |
398 | | SmallVectorImpl<MCFixup> &Fixups, |
399 | 3.03k | const MCSubtargetInfo &STI) const { |
400 | | |
401 | 3.03k | const MCOperand &MO = MI.getOperand(OpNo); |
402 | | // If the destination is an immediate, divide by 4. |
403 | 3.03k | if (MO.isImm()) return MO.getImm()>>2; |
404 | | |
405 | 3.03k | assert(MO.isExpr() && |
406 | 2.02k | "getJumpTargetOpValue expects only expressions or an immediate"); |
407 | | |
408 | 2.02k | const MCExpr *Expr = MO.getExpr(); |
409 | 2.02k | Fixups.push_back(MCFixup::create(0, Expr, |
410 | 2.02k | MCFixupKind(Mips::fixup_Mips_26))); |
411 | 2.02k | return 0; |
412 | 2.02k | } |
413 | | |
414 | | unsigned MipsMCCodeEmitter:: |
415 | | getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, |
416 | | SmallVectorImpl<MCFixup> &Fixups, |
417 | 0 | const MCSubtargetInfo &STI) const { |
418 | |
|
419 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
420 | | // If the destination is an immediate, divide by 2. |
421 | 0 | if (MO.isImm()) return MO.getImm() >> 1; |
422 | | |
423 | 0 | assert(MO.isExpr() && |
424 | 0 | "getJumpTargetOpValueMM expects only expressions or an immediate"); |
425 | | |
426 | 0 | const MCExpr *Expr = MO.getExpr(); |
427 | 0 | Fixups.push_back(MCFixup::create(0, Expr, |
428 | 0 | MCFixupKind(Mips::fixup_MICROMIPS_26_S1))); |
429 | 0 | return 0; |
430 | 0 | } |
431 | | |
432 | | unsigned MipsMCCodeEmitter:: |
433 | | getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, |
434 | | SmallVectorImpl<MCFixup> &Fixups, |
435 | 0 | const MCSubtargetInfo &STI) const { |
436 | |
|
437 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
438 | 0 | if (MO.isImm()) { |
439 | | // The immediate is encoded as 'immediate << 2'. |
440 | 0 | unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); |
441 | 0 | assert((Res & 3) == 0); |
442 | 0 | return Res >> 2; |
443 | 0 | } |
444 | | |
445 | 0 | assert(MO.isExpr() && |
446 | 0 | "getUImm5Lsl2Encoding expects only expressions or an immediate"); |
447 | | |
448 | 0 | return 0; |
449 | 0 | } |
450 | | |
451 | | unsigned MipsMCCodeEmitter:: |
452 | | getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, |
453 | | SmallVectorImpl<MCFixup> &Fixups, |
454 | 0 | const MCSubtargetInfo &STI) const { |
455 | |
|
456 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
457 | 0 | if (MO.isImm()) { |
458 | 0 | int Value = MO.getImm(); |
459 | 0 | return Value >> 2; |
460 | 0 | } |
461 | | |
462 | 0 | return 0; |
463 | 0 | } |
464 | | |
465 | | unsigned MipsMCCodeEmitter:: |
466 | | getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, |
467 | | SmallVectorImpl<MCFixup> &Fixups, |
468 | 0 | const MCSubtargetInfo &STI) const { |
469 | |
|
470 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
471 | 0 | if (MO.isImm()) { |
472 | 0 | unsigned Value = MO.getImm(); |
473 | 0 | return Value >> 2; |
474 | 0 | } |
475 | | |
476 | 0 | return 0; |
477 | 0 | } |
478 | | |
479 | | unsigned MipsMCCodeEmitter:: |
480 | | getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, |
481 | | SmallVectorImpl<MCFixup> &Fixups, |
482 | 0 | const MCSubtargetInfo &STI) const { |
483 | |
|
484 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
485 | 0 | if (MO.isImm()) { |
486 | 0 | unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff; |
487 | 0 | return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff)); |
488 | 0 | } |
489 | | |
490 | 0 | return 0; |
491 | 0 | } |
492 | | |
493 | | unsigned MipsMCCodeEmitter:: |
494 | | getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, |
495 | 11.6k | const MCSubtargetInfo &STI) const { |
496 | 11.6k | int64_t Res; |
497 | | |
498 | 11.6k | if (Expr->evaluateAsAbsolute(Res)) |
499 | 1.75k | return Res; |
500 | | |
501 | 9.90k | MCExpr::ExprKind Kind = Expr->getKind(); |
502 | 9.90k | if (Kind == MCExpr::Constant) { |
503 | 0 | return cast<MCConstantExpr>(Expr)->getValue(); |
504 | 0 | } |
505 | | |
506 | 9.90k | if (Kind == MCExpr::Binary) { |
507 | 5.41k | unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI); |
508 | 5.41k | Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI); |
509 | 5.41k | return Res; |
510 | 5.41k | } |
511 | | |
512 | 4.49k | if (Kind == MCExpr::Target) { |
513 | 368 | const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr); |
514 | | |
515 | 368 | Mips::Fixups FixupKind = Mips::Fixups(0); |
516 | 368 | switch (MipsExpr->getKind()) { |
517 | 0 | default: llvm_unreachable("Unsupported fixup kind for target expression!"); |
518 | 16 | case MipsMCExpr::VK_Mips_HIGHEST: |
519 | 16 | FixupKind = Mips::fixup_Mips_HIGHEST; |
520 | 16 | break; |
521 | 16 | case MipsMCExpr::VK_Mips_HIGHER: |
522 | 16 | FixupKind = Mips::fixup_Mips_HIGHER; |
523 | 16 | break; |
524 | 168 | case MipsMCExpr::VK_Mips_HI: |
525 | 168 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 |
526 | 168 | : Mips::fixup_Mips_HI16; |
527 | 168 | break; |
528 | 168 | case MipsMCExpr::VK_Mips_LO: |
529 | 168 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 |
530 | 168 | : Mips::fixup_Mips_LO16; |
531 | 168 | break; |
532 | 368 | } |
533 | 368 | Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind))); |
534 | 368 | return 0; |
535 | 368 | } |
536 | | |
537 | 4.12k | if (Kind == MCExpr::SymbolRef) { |
538 | 3.54k | Mips::Fixups FixupKind = Mips::Fixups(0); |
539 | | |
540 | 3.54k | switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { |
541 | 0 | default: llvm_unreachable("Unknown fixup kind!"); |
542 | 0 | break; |
543 | 1.47k | case MCSymbolRefExpr::VK_None: |
544 | 1.47k | FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64. |
545 | 1.47k | break; |
546 | 0 | case MCSymbolRefExpr::VK_Mips_GPOFF_HI : |
547 | 0 | FixupKind = Mips::fixup_Mips_GPOFF_HI; |
548 | 0 | break; |
549 | 0 | case MCSymbolRefExpr::VK_Mips_GPOFF_LO : |
550 | 0 | FixupKind = Mips::fixup_Mips_GPOFF_LO; |
551 | 0 | break; |
552 | 0 | case MCSymbolRefExpr::VK_Mips_GOT_PAGE : |
553 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE |
554 | 0 | : Mips::fixup_Mips_GOT_PAGE; |
555 | 0 | break; |
556 | 0 | case MCSymbolRefExpr::VK_Mips_GOT_OFST : |
557 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST |
558 | 0 | : Mips::fixup_Mips_GOT_OFST; |
559 | 0 | break; |
560 | 7 | case MCSymbolRefExpr::VK_Mips_GOT_DISP : |
561 | 7 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP |
562 | 7 | : Mips::fixup_Mips_GOT_DISP; |
563 | 7 | break; |
564 | 0 | case MCSymbolRefExpr::VK_Mips_GPREL: |
565 | 0 | FixupKind = Mips::fixup_Mips_GPREL16; |
566 | 0 | break; |
567 | 3 | case MCSymbolRefExpr::VK_Mips_GOT_CALL: |
568 | 3 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16 |
569 | 3 | : Mips::fixup_Mips_CALL16; |
570 | 3 | break; |
571 | 0 | case MCSymbolRefExpr::VK_Mips_GOT16: |
572 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 |
573 | 0 | : Mips::fixup_Mips_GOT_Global; |
574 | 0 | break; |
575 | 0 | case MCSymbolRefExpr::VK_Mips_GOT: |
576 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 |
577 | 0 | : Mips::fixup_Mips_GOT_Local; |
578 | 0 | break; |
579 | 1.03k | case MCSymbolRefExpr::VK_Mips_ABS_HI: |
580 | 1.03k | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 |
581 | 1.03k | : Mips::fixup_Mips_HI16; |
582 | 1.03k | break; |
583 | 1.03k | case MCSymbolRefExpr::VK_Mips_ABS_LO: |
584 | 1.03k | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 |
585 | 1.03k | : Mips::fixup_Mips_LO16; |
586 | 1.03k | break; |
587 | 0 | case MCSymbolRefExpr::VK_Mips_TLSGD: |
588 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD |
589 | 0 | : Mips::fixup_Mips_TLSGD; |
590 | 0 | break; |
591 | 0 | case MCSymbolRefExpr::VK_Mips_TLSLDM: |
592 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM |
593 | 0 | : Mips::fixup_Mips_TLSLDM; |
594 | 0 | break; |
595 | 0 | case MCSymbolRefExpr::VK_Mips_DTPREL_HI: |
596 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 |
597 | 0 | : Mips::fixup_Mips_DTPREL_HI; |
598 | 0 | break; |
599 | 0 | case MCSymbolRefExpr::VK_Mips_DTPREL_LO: |
600 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 |
601 | 0 | : Mips::fixup_Mips_DTPREL_LO; |
602 | 0 | break; |
603 | 0 | case MCSymbolRefExpr::VK_Mips_GOTTPREL: |
604 | 0 | FixupKind = Mips::fixup_Mips_GOTTPREL; |
605 | 0 | break; |
606 | 0 | case MCSymbolRefExpr::VK_Mips_TPREL_HI: |
607 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16 |
608 | 0 | : Mips::fixup_Mips_TPREL_HI; |
609 | 0 | break; |
610 | 0 | case MCSymbolRefExpr::VK_Mips_TPREL_LO: |
611 | 0 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 |
612 | 0 | : Mips::fixup_Mips_TPREL_LO; |
613 | 0 | break; |
614 | 0 | case MCSymbolRefExpr::VK_Mips_HIGHER: |
615 | 0 | FixupKind = Mips::fixup_Mips_HIGHER; |
616 | 0 | break; |
617 | 0 | case MCSymbolRefExpr::VK_Mips_HIGHEST: |
618 | 0 | FixupKind = Mips::fixup_Mips_HIGHEST; |
619 | 0 | break; |
620 | 0 | case MCSymbolRefExpr::VK_Mips_GOT_HI16: |
621 | 0 | FixupKind = Mips::fixup_Mips_GOT_HI16; |
622 | 0 | break; |
623 | 0 | case MCSymbolRefExpr::VK_Mips_GOT_LO16: |
624 | 0 | FixupKind = Mips::fixup_Mips_GOT_LO16; |
625 | 0 | break; |
626 | 0 | case MCSymbolRefExpr::VK_Mips_CALL_HI16: |
627 | 0 | FixupKind = Mips::fixup_Mips_CALL_HI16; |
628 | 0 | break; |
629 | 0 | case MCSymbolRefExpr::VK_Mips_CALL_LO16: |
630 | 0 | FixupKind = Mips::fixup_Mips_CALL_LO16; |
631 | 0 | break; |
632 | 0 | case MCSymbolRefExpr::VK_Mips_PCREL_HI16: |
633 | 0 | FixupKind = Mips::fixup_MIPS_PCHI16; |
634 | 0 | break; |
635 | 0 | case MCSymbolRefExpr::VK_Mips_PCREL_LO16: |
636 | 0 | FixupKind = Mips::fixup_MIPS_PCLO16; |
637 | 0 | break; |
638 | 3.54k | } // switch |
639 | | |
640 | 3.54k | Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); |
641 | 3.54k | return 0; |
642 | 3.54k | } |
643 | 575 | return 0; |
644 | 4.12k | } |
645 | | |
646 | | /// getMachineOpValue - Return binary encoding of operand. If the machine |
647 | | /// operand requires relocation, record the relocation and return zero. |
648 | | unsigned MipsMCCodeEmitter:: |
649 | | getMachineOpValue(const MCInst &MI, const MCOperand &MO, |
650 | | SmallVectorImpl<MCFixup> &Fixups, |
651 | 54.7k | const MCSubtargetInfo &STI) const { |
652 | 54.7k | if (MO.isReg()) { |
653 | 41.6k | unsigned Reg = MO.getReg(); |
654 | 41.6k | unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); |
655 | 41.6k | return RegNo; |
656 | 41.6k | } else if (MO.isImm()) { |
657 | 12.3k | return static_cast<unsigned>(MO.getImm()); |
658 | 12.3k | } else if (MO.isFPImm()) { |
659 | 0 | return static_cast<unsigned>(APFloat(MO.getFPImm()) |
660 | 0 | .bitcastToAPInt().getHiBits(32).getLimitedValue()); |
661 | 0 | } |
662 | | // MO must be an Expr. |
663 | 54.7k | assert(MO.isExpr()); |
664 | 836 | return getExprOpValue(MO.getExpr(),Fixups, STI); |
665 | 836 | } |
666 | | |
667 | | /// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST |
668 | | /// instructions. |
669 | | unsigned |
670 | | MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo, |
671 | | SmallVectorImpl<MCFixup> &Fixups, |
672 | 0 | const MCSubtargetInfo &STI) const { |
673 | | // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. |
674 | 0 | assert(MI.getOperand(OpNo).isReg()); |
675 | 0 | unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; |
676 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); |
677 | | |
678 | | // The immediate field of an LD/ST instruction is scaled which means it must |
679 | | // be divided (when encoding) by the size (in bytes) of the instructions' |
680 | | // data format. |
681 | | // .b - 1 byte |
682 | | // .h - 2 bytes |
683 | | // .w - 4 bytes |
684 | | // .d - 8 bytes |
685 | 0 | switch(MI.getOpcode()) |
686 | 0 | { |
687 | 0 | default: |
688 | 0 | assert (0 && "Unexpected instruction"); |
689 | 0 | break; |
690 | 0 | case Mips::LD_B: |
691 | 0 | case Mips::ST_B: |
692 | | // We don't need to scale the offset in this case |
693 | 0 | break; |
694 | 0 | case Mips::LD_H: |
695 | 0 | case Mips::ST_H: |
696 | 0 | OffBits >>= 1; |
697 | 0 | break; |
698 | 0 | case Mips::LD_W: |
699 | 0 | case Mips::ST_W: |
700 | 0 | OffBits >>= 2; |
701 | 0 | break; |
702 | 0 | case Mips::LD_D: |
703 | 0 | case Mips::ST_D: |
704 | 0 | OffBits >>= 3; |
705 | 0 | break; |
706 | 0 | } |
707 | | |
708 | 0 | return (OffBits & 0xFFFF) | RegBits; |
709 | 0 | } |
710 | | |
711 | | /// getMemEncoding - Return binary encoding of memory related operand. |
712 | | /// If the offset operand requires relocation, record the relocation. |
713 | | unsigned |
714 | | MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, |
715 | | SmallVectorImpl<MCFixup> &Fixups, |
716 | 681 | const MCSubtargetInfo &STI) const { |
717 | | // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. |
718 | 681 | assert(MI.getOperand(OpNo).isReg()); |
719 | 681 | unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; |
720 | 681 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); |
721 | | |
722 | 681 | return (OffBits & 0xFFFF) | RegBits; |
723 | 681 | } |
724 | | |
725 | | unsigned MipsMCCodeEmitter:: |
726 | | getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, |
727 | | SmallVectorImpl<MCFixup> &Fixups, |
728 | 0 | const MCSubtargetInfo &STI) const { |
729 | | // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. |
730 | 0 | assert(MI.getOperand(OpNo).isReg()); |
731 | 0 | unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), |
732 | 0 | Fixups, STI) << 4; |
733 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), |
734 | 0 | Fixups, STI); |
735 | |
|
736 | 0 | return (OffBits & 0xF) | RegBits; |
737 | 0 | } |
738 | | |
739 | | unsigned MipsMCCodeEmitter:: |
740 | | getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, |
741 | | SmallVectorImpl<MCFixup> &Fixups, |
742 | 0 | const MCSubtargetInfo &STI) const { |
743 | | // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. |
744 | 0 | assert(MI.getOperand(OpNo).isReg()); |
745 | 0 | unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), |
746 | 0 | Fixups, STI) << 4; |
747 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), |
748 | 0 | Fixups, STI) >> 1; |
749 | |
|
750 | 0 | return (OffBits & 0xF) | RegBits; |
751 | 0 | } |
752 | | |
753 | | unsigned MipsMCCodeEmitter:: |
754 | | getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, |
755 | | SmallVectorImpl<MCFixup> &Fixups, |
756 | 0 | const MCSubtargetInfo &STI) const { |
757 | | // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. |
758 | 0 | assert(MI.getOperand(OpNo).isReg()); |
759 | 0 | unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), |
760 | 0 | Fixups, STI) << 4; |
761 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), |
762 | 0 | Fixups, STI) >> 2; |
763 | |
|
764 | 0 | return (OffBits & 0xF) | RegBits; |
765 | 0 | } |
766 | | |
767 | | unsigned MipsMCCodeEmitter:: |
768 | | getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, |
769 | | SmallVectorImpl<MCFixup> &Fixups, |
770 | 0 | const MCSubtargetInfo &STI) const { |
771 | | // Register is encoded in bits 9-5, offset is encoded in bits 4-0. |
772 | 0 | assert(MI.getOperand(OpNo).isReg() && |
773 | 0 | (MI.getOperand(OpNo).getReg() == Mips::SP || |
774 | 0 | MI.getOperand(OpNo).getReg() == Mips::SP_64) && |
775 | 0 | "Unexpected base register!"); |
776 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), |
777 | 0 | Fixups, STI) >> 2; |
778 | |
|
779 | 0 | return OffBits & 0x1F; |
780 | 0 | } |
781 | | |
782 | | unsigned MipsMCCodeEmitter:: |
783 | | getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, |
784 | | SmallVectorImpl<MCFixup> &Fixups, |
785 | 0 | const MCSubtargetInfo &STI) const { |
786 | | // Register is encoded in bits 9-7, offset is encoded in bits 6-0. |
787 | 0 | assert(MI.getOperand(OpNo).isReg() && |
788 | 0 | MI.getOperand(OpNo).getReg() == Mips::GP && |
789 | 0 | "Unexpected base register!"); |
790 | | |
791 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), |
792 | 0 | Fixups, STI) >> 2; |
793 | |
|
794 | 0 | return OffBits & 0x7F; |
795 | 0 | } |
796 | | |
797 | | unsigned MipsMCCodeEmitter:: |
798 | | getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, |
799 | | SmallVectorImpl<MCFixup> &Fixups, |
800 | 0 | const MCSubtargetInfo &STI) const { |
801 | | // Base register is encoded in bits 20-16, offset is encoded in bits 8-0. |
802 | 0 | assert(MI.getOperand(OpNo).isReg()); |
803 | 0 | unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, |
804 | 0 | STI) << 16; |
805 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI); |
806 | |
|
807 | 0 | return (OffBits & 0x1FF) | RegBits; |
808 | 0 | } |
809 | | |
810 | | unsigned MipsMCCodeEmitter:: |
811 | | getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, |
812 | | SmallVectorImpl<MCFixup> &Fixups, |
813 | 0 | const MCSubtargetInfo &STI) const { |
814 | | // opNum can be invalid if instruction had reglist as operand. |
815 | | // MemOperand is always last operand of instruction (base + offset). |
816 | 0 | switch (MI.getOpcode()) { |
817 | 0 | default: |
818 | 0 | break; |
819 | 0 | case Mips::SWM32_MM: |
820 | 0 | case Mips::LWM32_MM: |
821 | 0 | OpNo = MI.getNumOperands() - 2; |
822 | 0 | break; |
823 | 0 | } |
824 | | |
825 | | // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. |
826 | 0 | assert(MI.getOperand(OpNo).isReg()); |
827 | 0 | unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16; |
828 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); |
829 | |
|
830 | 0 | return (OffBits & 0x0FFF) | RegBits; |
831 | 0 | } |
832 | | |
833 | | unsigned MipsMCCodeEmitter:: |
834 | | getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo, |
835 | | SmallVectorImpl<MCFixup> &Fixups, |
836 | 0 | const MCSubtargetInfo &STI) const { |
837 | | // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. |
838 | 0 | assert(MI.getOperand(OpNo).isReg()); |
839 | 0 | unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, |
840 | 0 | STI) << 16; |
841 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); |
842 | |
|
843 | 0 | return (OffBits & 0xFFFF) | RegBits; |
844 | 0 | } |
845 | | |
846 | | unsigned MipsMCCodeEmitter:: |
847 | | getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, |
848 | | SmallVectorImpl<MCFixup> &Fixups, |
849 | 0 | const MCSubtargetInfo &STI) const { |
850 | | // opNum can be invalid if instruction had reglist as operand |
851 | | // MemOperand is always last operand of instruction (base + offset) |
852 | 0 | switch (MI.getOpcode()) { |
853 | 0 | default: |
854 | 0 | break; |
855 | 0 | case Mips::SWM16_MM: |
856 | 0 | case Mips::SWM16_MMR6: |
857 | 0 | case Mips::LWM16_MM: |
858 | 0 | case Mips::LWM16_MMR6: |
859 | 0 | OpNo = MI.getNumOperands() - 2; |
860 | 0 | break; |
861 | 0 | } |
862 | | |
863 | | // Offset is encoded in bits 4-0. |
864 | 0 | assert(MI.getOperand(OpNo).isReg()); |
865 | | // Base register is always SP - thus it is not encoded. |
866 | 0 | assert(MI.getOperand(OpNo+1).isImm()); |
867 | 0 | unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); |
868 | |
|
869 | 0 | return ((OffBits >> 2) & 0x0F); |
870 | 0 | } |
871 | | |
872 | | // FIXME: should be called getMSBEncoding |
873 | | // |
874 | | unsigned |
875 | | MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, |
876 | | SmallVectorImpl<MCFixup> &Fixups, |
877 | 0 | const MCSubtargetInfo &STI) const { |
878 | 0 | assert(MI.getOperand(OpNo-1).isImm()); |
879 | 0 | assert(MI.getOperand(OpNo).isImm()); |
880 | 0 | unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI); |
881 | 0 | unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); |
882 | |
|
883 | 0 | return Position + Size - 1; |
884 | 0 | } |
885 | | |
886 | | template <unsigned Bits, int Offset> |
887 | | unsigned |
888 | | MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, |
889 | | SmallVectorImpl<MCFixup> &Fixups, |
890 | 0 | const MCSubtargetInfo &STI) const { |
891 | 0 | assert(MI.getOperand(OpNo).isImm()); |
892 | 0 | unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); |
893 | 0 | Value -= Offset; |
894 | 0 | return Value; |
895 | 0 | } Unexecuted instantiation: unsigned int llvm_ks::MipsMCCodeEmitter::getUImmWithOffsetEncoding<2u, 1>(llvm_ks::MCInst const&, unsigned int, llvm_ks::SmallVectorImpl<llvm_ks::MCFixup>&, llvm_ks::MCSubtargetInfo const&) const Unexecuted instantiation: unsigned int llvm_ks::MipsMCCodeEmitter::getUImmWithOffsetEncoding<5u, 1>(llvm_ks::MCInst const&, unsigned int, llvm_ks::SmallVectorImpl<llvm_ks::MCFixup>&, llvm_ks::MCSubtargetInfo const&) const |
896 | | |
897 | | unsigned |
898 | | MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo, |
899 | | SmallVectorImpl<MCFixup> &Fixups, |
900 | 0 | const MCSubtargetInfo &STI) const { |
901 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
902 | 0 | if (MO.isImm()) { |
903 | | // The immediate is encoded as 'immediate << 2'. |
904 | 0 | unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); |
905 | 0 | assert((Res & 3) == 0); |
906 | 0 | return Res >> 2; |
907 | 0 | } |
908 | | |
909 | 0 | assert(MO.isExpr() && |
910 | 0 | "getSimm19Lsl2Encoding expects only expressions or an immediate"); |
911 | | |
912 | 0 | const MCExpr *Expr = MO.getExpr(); |
913 | 0 | Fixups.push_back(MCFixup::create(0, Expr, |
914 | 0 | MCFixupKind(Mips::fixup_MIPS_PC19_S2))); |
915 | 0 | return 0; |
916 | 0 | } |
917 | | |
918 | | unsigned |
919 | | MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo, |
920 | | SmallVectorImpl<MCFixup> &Fixups, |
921 | 0 | const MCSubtargetInfo &STI) const { |
922 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
923 | 0 | if (MO.isImm()) { |
924 | | // The immediate is encoded as 'immediate << 3'. |
925 | 0 | unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); |
926 | 0 | assert((Res & 7) == 0); |
927 | 0 | return Res >> 3; |
928 | 0 | } |
929 | | |
930 | 0 | assert(MO.isExpr() && |
931 | 0 | "getSimm18Lsl2Encoding expects only expressions or an immediate"); |
932 | | |
933 | 0 | const MCExpr *Expr = MO.getExpr(); |
934 | 0 | Fixups.push_back(MCFixup::create(0, Expr, |
935 | 0 | MCFixupKind(Mips::fixup_MIPS_PC18_S3))); |
936 | 0 | return 0; |
937 | 0 | } |
938 | | |
939 | | unsigned |
940 | | MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, |
941 | | SmallVectorImpl<MCFixup> &Fixups, |
942 | 0 | const MCSubtargetInfo &STI) const { |
943 | 0 | assert(MI.getOperand(OpNo).isImm()); |
944 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
945 | 0 | return MO.getImm() % 8; |
946 | 0 | } |
947 | | |
948 | | unsigned |
949 | | MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo, |
950 | | SmallVectorImpl<MCFixup> &Fixups, |
951 | 0 | const MCSubtargetInfo &STI) const { |
952 | 0 | assert(MI.getOperand(OpNo).isImm()); |
953 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
954 | 0 | unsigned Value = MO.getImm(); |
955 | 0 | switch (Value) { |
956 | 0 | case 128: return 0x0; |
957 | 0 | case 1: return 0x1; |
958 | 0 | case 2: return 0x2; |
959 | 0 | case 3: return 0x3; |
960 | 0 | case 4: return 0x4; |
961 | 0 | case 7: return 0x5; |
962 | 0 | case 8: return 0x6; |
963 | 0 | case 15: return 0x7; |
964 | 0 | case 16: return 0x8; |
965 | 0 | case 31: return 0x9; |
966 | 0 | case 32: return 0xa; |
967 | 0 | case 63: return 0xb; |
968 | 0 | case 64: return 0xc; |
969 | 0 | case 255: return 0xd; |
970 | 0 | case 32768: return 0xe; |
971 | 0 | case 65535: return 0xf; |
972 | 0 | } |
973 | 0 | llvm_unreachable("Unexpected value"); |
974 | 0 | } |
975 | | |
976 | | unsigned |
977 | | MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, |
978 | | SmallVectorImpl<MCFixup> &Fixups, |
979 | 0 | const MCSubtargetInfo &STI) const { |
980 | 0 | unsigned res = 0; |
981 | | |
982 | | // Register list operand is always first operand of instruction and it is |
983 | | // placed before memory operand (register + imm). |
984 | |
|
985 | 0 | for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) { |
986 | 0 | unsigned Reg = MI.getOperand(I).getReg(); |
987 | 0 | unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); |
988 | 0 | if (RegNo != 31) |
989 | 0 | res++; |
990 | 0 | else |
991 | 0 | res |= 0x10; |
992 | 0 | } |
993 | 0 | return res; |
994 | 0 | } |
995 | | |
996 | | unsigned |
997 | | MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, |
998 | | SmallVectorImpl<MCFixup> &Fixups, |
999 | 0 | const MCSubtargetInfo &STI) const { |
1000 | 0 | return (MI.getNumOperands() - 4); |
1001 | 0 | } |
1002 | | |
1003 | | unsigned |
1004 | | MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, |
1005 | | SmallVectorImpl<MCFixup> &Fixups, |
1006 | 0 | const MCSubtargetInfo &STI) const { |
1007 | 0 | return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); |
1008 | 0 | } |
1009 | | |
1010 | | unsigned |
1011 | | MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, |
1012 | | SmallVectorImpl<MCFixup> &Fixups, |
1013 | 0 | const MCSubtargetInfo &STI) const { |
1014 | 0 | unsigned res = 0; |
1015 | |
|
1016 | 0 | if (MI.getOperand(0).getReg() == Mips::A1 && |
1017 | 0 | MI.getOperand(1).getReg() == Mips::A2) |
1018 | 0 | res = 0; |
1019 | 0 | else if (MI.getOperand(0).getReg() == Mips::A1 && |
1020 | 0 | MI.getOperand(1).getReg() == Mips::A3) |
1021 | 0 | res = 1; |
1022 | 0 | else if (MI.getOperand(0).getReg() == Mips::A2 && |
1023 | 0 | MI.getOperand(1).getReg() == Mips::A3) |
1024 | 0 | res = 2; |
1025 | 0 | else if (MI.getOperand(0).getReg() == Mips::A0 && |
1026 | 0 | MI.getOperand(1).getReg() == Mips::S5) |
1027 | 0 | res = 3; |
1028 | 0 | else if (MI.getOperand(0).getReg() == Mips::A0 && |
1029 | 0 | MI.getOperand(1).getReg() == Mips::S6) |
1030 | 0 | res = 4; |
1031 | 0 | else if (MI.getOperand(0).getReg() == Mips::A0 && |
1032 | 0 | MI.getOperand(1).getReg() == Mips::A1) |
1033 | 0 | res = 5; |
1034 | 0 | else if (MI.getOperand(0).getReg() == Mips::A0 && |
1035 | 0 | MI.getOperand(1).getReg() == Mips::A2) |
1036 | 0 | res = 6; |
1037 | 0 | else if (MI.getOperand(0).getReg() == Mips::A0 && |
1038 | 0 | MI.getOperand(1).getReg() == Mips::A3) |
1039 | 0 | res = 7; |
1040 | |
|
1041 | 0 | return res; |
1042 | 0 | } |
1043 | | |
1044 | | unsigned |
1045 | | MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, |
1046 | | SmallVectorImpl<MCFixup> &Fixups, |
1047 | 0 | const MCSubtargetInfo &STI) const { |
1048 | 0 | const MCOperand &MO = MI.getOperand(OpNo); |
1049 | 0 | assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate"); |
1050 | | // The immediate is encoded as 'immediate >> 2'. |
1051 | 0 | unsigned Res = static_cast<unsigned>(MO.getImm()); |
1052 | 0 | assert((Res & 3) == 0); |
1053 | 0 | return Res >> 2; |
1054 | 0 | } |
1055 | | |
1056 | | #include "MipsGenMCCodeEmitter.inc" |