1 | //===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements the MipsMCCodeEmitter class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "MipsMCCodeEmitter.h" |
14 | #include "MCTargetDesc/MipsFixupKinds.h" |
15 | #include "MCTargetDesc/MipsMCExpr.h" |
16 | #include "MCTargetDesc/MipsMCTargetDesc.h" |
17 | #include "llvm/ADT/APFloat.h" |
18 | #include "llvm/ADT/APInt.h" |
19 | #include "llvm/ADT/SmallVector.h" |
20 | #include "llvm/MC/MCContext.h" |
21 | #include "llvm/MC/MCExpr.h" |
22 | #include "llvm/MC/MCFixup.h" |
23 | #include "llvm/MC/MCInst.h" |
24 | #include "llvm/MC/MCInstrDesc.h" |
25 | #include "llvm/MC/MCInstrInfo.h" |
26 | #include "llvm/MC/MCRegisterInfo.h" |
27 | #include "llvm/MC/MCSubtargetInfo.h" |
28 | #include "llvm/Support/Casting.h" |
29 | #include "llvm/Support/EndianStream.h" |
30 | #include "llvm/Support/ErrorHandling.h" |
31 | #include "llvm/Support/raw_ostream.h" |
32 | #include <cassert> |
33 | #include <cstdint> |
34 | |
35 | using namespace llvm; |
36 | |
37 | #define DEBUG_TYPE "mccodeemitter" |
38 | |
39 | #define GET_INSTRMAP_INFO |
40 | #include "MipsGenInstrInfo.inc" |
41 | #undef GET_INSTRMAP_INFO |
42 | |
43 | namespace llvm { |
44 | |
45 | MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, |
46 | MCContext &Ctx) { |
47 | return new MipsMCCodeEmitter(MCII, Ctx, false); |
48 | } |
49 | |
50 | MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, |
51 | MCContext &Ctx) { |
52 | return new MipsMCCodeEmitter(MCII, Ctx, true); |
53 | } |
54 | |
55 | } // end namespace llvm |
56 | |
57 | // If the D<shift> instruction has a shift amount that is greater |
58 | // than 31 (checked in calling routine), lower it to a D<shift>32 instruction |
59 | static void LowerLargeShift(MCInst& Inst) { |
60 | assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!" ); |
61 | assert(Inst.getOperand(2).isImm()); |
62 | |
63 | int64_t Shift = Inst.getOperand(i: 2).getImm(); |
64 | if (Shift <= 31) |
65 | return; // Do nothing |
66 | Shift -= 32; |
67 | |
68 | // saminus32 |
69 | Inst.getOperand(i: 2).setImm(Shift); |
70 | |
71 | switch (Inst.getOpcode()) { |
72 | default: |
73 | // Calling function is not synchronized |
74 | llvm_unreachable("Unexpected shift instruction" ); |
75 | case Mips::DSLL: |
76 | Inst.setOpcode(Mips::DSLL32); |
77 | return; |
78 | case Mips::DSRL: |
79 | Inst.setOpcode(Mips::DSRL32); |
80 | return; |
81 | case Mips::DSRA: |
82 | Inst.setOpcode(Mips::DSRA32); |
83 | return; |
84 | case Mips::DROTR: |
85 | Inst.setOpcode(Mips::DROTR32); |
86 | return; |
87 | } |
88 | } |
89 | |
90 | // Fix a bad compact branch encoding for beqc/bnec. |
91 | void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const { |
92 | // Encoding may be illegal !(rs < rt), but this situation is |
93 | // easily fixed. |
94 | unsigned RegOp0 = Inst.getOperand(i: 0).getReg(); |
95 | unsigned RegOp1 = Inst.getOperand(i: 1).getReg(); |
96 | |
97 | unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(RegNo: RegOp0); |
98 | unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(RegNo: RegOp1); |
99 | |
100 | if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC || |
101 | Inst.getOpcode() == Mips::BNEC64 || Inst.getOpcode() == Mips::BEQC64) { |
102 | assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!" ); |
103 | if (Reg0 < Reg1) |
104 | return; |
105 | } else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) { |
106 | if (Reg0 >= Reg1) |
107 | return; |
108 | } else if (Inst.getOpcode() == Mips::BNVC_MMR6 || |
109 | Inst.getOpcode() == Mips::BOVC_MMR6) { |
110 | if (Reg1 >= Reg0) |
111 | return; |
112 | } else |
113 | llvm_unreachable("Cannot rewrite unknown branch!" ); |
114 | |
115 | Inst.getOperand(i: 0).setReg(RegOp1); |
116 | Inst.getOperand(i: 1).setReg(RegOp0); |
117 | } |
118 | |
119 | bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { |
120 | return STI.hasFeature(Feature: Mips::FeatureMicroMips); |
121 | } |
122 | |
123 | bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const { |
124 | return STI.hasFeature(Feature: Mips::FeatureMips32r6); |
125 | } |
126 | |
127 | void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { |
128 | OS << (char)C; |
129 | } |
130 | |
131 | /// encodeInstruction - Emit the instruction. |
132 | /// Size the instruction with Desc.getSize(). |
133 | void MipsMCCodeEmitter::encodeInstruction(const MCInst &MI, |
134 | SmallVectorImpl<char> &CB, |
135 | SmallVectorImpl<MCFixup> &Fixups, |
136 | const MCSubtargetInfo &STI) const { |
137 | // Non-pseudo instructions that get changed for direct object |
138 | // only based on operand values. |
139 | // If this list of instructions get much longer we will move |
140 | // the check to a function call. Until then, this is more efficient. |
141 | MCInst TmpInst = MI; |
142 | switch (MI.getOpcode()) { |
143 | // If shift amount is >= 32 it the inst needs to be lowered further |
144 | case Mips::DSLL: |
145 | case Mips::DSRL: |
146 | case Mips::DSRA: |
147 | case Mips::DROTR: |
148 | LowerLargeShift(Inst&: TmpInst); |
149 | break; |
150 | // Compact branches, enforce encoding restrictions. |
151 | case Mips::BEQC: |
152 | case Mips::BNEC: |
153 | case Mips::BEQC64: |
154 | case Mips::BNEC64: |
155 | case Mips::BOVC: |
156 | case Mips::BOVC_MMR6: |
157 | case Mips::BNVC: |
158 | case Mips::BNVC_MMR6: |
159 | LowerCompactBranch(Inst&: TmpInst); |
160 | } |
161 | |
162 | size_t N = Fixups.size(); |
163 | uint32_t Binary = getBinaryCodeForInstr(MI: TmpInst, Fixups, STI); |
164 | |
165 | // Check for unimplemented opcodes. |
166 | // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 |
167 | // so we have to special check for them. |
168 | const unsigned Opcode = TmpInst.getOpcode(); |
169 | if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && |
170 | (Opcode != Mips::SLL_MM) && (Opcode != Mips::SLL_MMR6) && !Binary) |
171 | llvm_unreachable("unimplemented opcode in encodeInstruction()" ); |
172 | |
173 | int NewOpcode = -1; |
174 | if (isMicroMips(STI)) { |
175 | if (isMips32r6(STI)) { |
176 | NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, inArch: Mips::Arch_micromipsr6); |
177 | if (NewOpcode == -1) |
178 | NewOpcode = Mips::Std2MicroMipsR6(Opcode, inArch: Mips::Arch_micromipsr6); |
179 | } |
180 | else |
181 | NewOpcode = Mips::Std2MicroMips(Opcode, inArch: Mips::Arch_micromips); |
182 | |
183 | // Check whether it is Dsp instruction. |
184 | if (NewOpcode == -1) |
185 | NewOpcode = Mips::Dsp2MicroMips(Opcode, inArch: Mips::Arch_mmdsp); |
186 | |
187 | if (NewOpcode != -1) { |
188 | if (Fixups.size() > N) |
189 | Fixups.pop_back(); |
190 | |
191 | TmpInst.setOpcode (NewOpcode); |
192 | Binary = getBinaryCodeForInstr(MI: TmpInst, Fixups, STI); |
193 | } |
194 | |
195 | if (((MI.getOpcode() == Mips::MOVEP_MM) || |
196 | (MI.getOpcode() == Mips::MOVEP_MMR6))) { |
197 | unsigned RegPair = getMovePRegPairOpValue(MI, OpNo: 0, Fixups, STI); |
198 | Binary = (Binary & 0xFFFFFC7F) | (RegPair << 7); |
199 | } |
200 | } |
201 | |
202 | const MCInstrDesc &Desc = MCII.get(Opcode: TmpInst.getOpcode()); |
203 | |
204 | // Get byte count of instruction |
205 | unsigned Size = Desc.getSize(); |
206 | if (!Size) |
207 | llvm_unreachable("Desc.getSize() returns 0" ); |
208 | |
209 | auto Endian = |
210 | IsLittleEndian ? llvm::endianness::little : llvm::endianness::big; |
211 | if (Size == 2) { |
212 | support::endian::write<uint16_t>(Out&: CB, V: Binary, E: Endian); |
213 | } else if (IsLittleEndian && isMicroMips(STI)) { |
214 | support::endian::write<uint16_t>(Out&: CB, V: Binary >> 16, E: Endian); |
215 | support::endian::write<uint16_t>(Out&: CB, V: Binary & 0xffff, E: Endian); |
216 | } else { |
217 | support::endian::write<uint32_t>(Out&: CB, V: Binary, E: Endian); |
218 | } |
219 | } |
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 | const MCSubtargetInfo &STI) const { |
228 | const MCOperand &MO = MI.getOperand(i: OpNo); |
229 | |
230 | // If the destination is an immediate, divide by 4. |
231 | if (MO.isImm()) return MO.getImm() >> 2; |
232 | |
233 | assert(MO.isExpr() && |
234 | "getBranchTargetOpValue expects only expressions or immediates" ); |
235 | |
236 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
237 | LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx); |
238 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: FixupExpression, |
239 | Kind: MCFixupKind(Mips::fixup_Mips_PC16))); |
240 | return 0; |
241 | } |
242 | |
243 | /// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch |
244 | /// target operand. If the machine operand requires relocation, |
245 | /// record the relocation and return zero. |
246 | unsigned MipsMCCodeEmitter:: |
247 | getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo, |
248 | SmallVectorImpl<MCFixup> &Fixups, |
249 | const MCSubtargetInfo &STI) const { |
250 | const MCOperand &MO = MI.getOperand(i: OpNo); |
251 | |
252 | // If the destination is an immediate, divide by 2. |
253 | if (MO.isImm()) return MO.getImm() >> 1; |
254 | |
255 | assert(MO.isExpr() && |
256 | "getBranchTargetOpValue expects only expressions or immediates" ); |
257 | |
258 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
259 | LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx); |
260 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: FixupExpression, |
261 | Kind: MCFixupKind(Mips::fixup_Mips_PC16))); |
262 | return 0; |
263 | } |
264 | |
265 | /// getBranchTargetOpValueMMR6 - Return binary encoding of the branch |
266 | /// target operand. If the machine operand requires relocation, |
267 | /// record the relocation and return zero. |
268 | unsigned MipsMCCodeEmitter:: |
269 | getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo, |
270 | SmallVectorImpl<MCFixup> &Fixups, |
271 | const MCSubtargetInfo &STI) const { |
272 | const MCOperand &MO = MI.getOperand(i: OpNo); |
273 | |
274 | // If the destination is an immediate, divide by 2. |
275 | if (MO.isImm()) |
276 | return MO.getImm() >> 1; |
277 | |
278 | assert(MO.isExpr() && |
279 | "getBranchTargetOpValueMMR6 expects only expressions or immediates" ); |
280 | |
281 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
282 | LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -2, Ctx), Ctx); |
283 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: FixupExpression, |
284 | Kind: MCFixupKind(Mips::fixup_Mips_PC16))); |
285 | return 0; |
286 | } |
287 | |
288 | /// getBranchTargetOpValueLsl2MMR6 - Return binary encoding of the branch |
289 | /// target operand. If the machine operand requires relocation, |
290 | /// record the relocation and return zero. |
291 | unsigned MipsMCCodeEmitter:: |
292 | getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo, |
293 | SmallVectorImpl<MCFixup> &Fixups, |
294 | const MCSubtargetInfo &STI) const { |
295 | const MCOperand &MO = MI.getOperand(i: OpNo); |
296 | |
297 | // If the destination is an immediate, divide by 4. |
298 | if (MO.isImm()) |
299 | return MO.getImm() >> 2; |
300 | |
301 | assert(MO.isExpr() && |
302 | "getBranchTargetOpValueLsl2MMR6 expects only expressions or immediates" ); |
303 | |
304 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
305 | LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx); |
306 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: FixupExpression, |
307 | Kind: MCFixupKind(Mips::fixup_Mips_PC16))); |
308 | return 0; |
309 | } |
310 | |
311 | /// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch |
312 | /// target operand. If the machine operand requires relocation, |
313 | /// record the relocation and return zero. |
314 | unsigned MipsMCCodeEmitter:: |
315 | getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, |
316 | SmallVectorImpl<MCFixup> &Fixups, |
317 | const MCSubtargetInfo &STI) const { |
318 | const MCOperand &MO = MI.getOperand(i: OpNo); |
319 | |
320 | // If the destination is an immediate, divide by 2. |
321 | if (MO.isImm()) return MO.getImm() >> 1; |
322 | |
323 | assert(MO.isExpr() && |
324 | "getBranchTargetOpValueMM expects only expressions or immediates" ); |
325 | |
326 | const MCExpr *Expr = MO.getExpr(); |
327 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, |
328 | Kind: MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1))); |
329 | return 0; |
330 | } |
331 | |
332 | /// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS |
333 | /// 10-bit branch target operand. If the machine operand requires relocation, |
334 | /// record the relocation and return zero. |
335 | unsigned MipsMCCodeEmitter:: |
336 | getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, |
337 | SmallVectorImpl<MCFixup> &Fixups, |
338 | const MCSubtargetInfo &STI) const { |
339 | const MCOperand &MO = MI.getOperand(i: OpNo); |
340 | |
341 | // If the destination is an immediate, divide by 2. |
342 | if (MO.isImm()) return MO.getImm() >> 1; |
343 | |
344 | assert(MO.isExpr() && |
345 | "getBranchTargetOpValuePC10 expects only expressions or immediates" ); |
346 | |
347 | const MCExpr *Expr = MO.getExpr(); |
348 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, |
349 | Kind: MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1))); |
350 | return 0; |
351 | } |
352 | |
353 | /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch |
354 | /// target operand. If the machine operand requires relocation, |
355 | /// record the relocation and return zero. |
356 | unsigned MipsMCCodeEmitter:: |
357 | getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, |
358 | SmallVectorImpl<MCFixup> &Fixups, |
359 | const MCSubtargetInfo &STI) const { |
360 | const MCOperand &MO = MI.getOperand(i: OpNo); |
361 | |
362 | // If the destination is an immediate, divide by 2. |
363 | if (MO.isImm()) return MO.getImm() >> 1; |
364 | |
365 | assert(MO.isExpr() && |
366 | "getBranchTargetOpValueMM expects only expressions or immediates" ); |
367 | |
368 | const MCExpr *Expr = MO.getExpr(); |
369 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, |
370 | Kind: MCFixupKind(Mips:: |
371 | fixup_MICROMIPS_PC16_S1))); |
372 | return 0; |
373 | } |
374 | |
375 | /// getBranchTarget21OpValue - Return binary encoding of the branch |
376 | /// target operand. If the machine operand requires relocation, |
377 | /// record the relocation and return zero. |
378 | unsigned MipsMCCodeEmitter:: |
379 | getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, |
380 | SmallVectorImpl<MCFixup> &Fixups, |
381 | const MCSubtargetInfo &STI) const { |
382 | const MCOperand &MO = MI.getOperand(i: OpNo); |
383 | |
384 | // If the destination is an immediate, divide by 4. |
385 | if (MO.isImm()) return MO.getImm() >> 2; |
386 | |
387 | assert(MO.isExpr() && |
388 | "getBranchTarget21OpValue expects only expressions or immediates" ); |
389 | |
390 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
391 | LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx); |
392 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: FixupExpression, |
393 | Kind: MCFixupKind(Mips::fixup_MIPS_PC21_S2))); |
394 | return 0; |
395 | } |
396 | |
397 | /// getBranchTarget21OpValueMM - Return binary encoding of the branch |
398 | /// target operand for microMIPS. If the machine operand requires |
399 | /// relocation, record the relocation and return zero. |
400 | unsigned MipsMCCodeEmitter:: |
401 | getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo, |
402 | SmallVectorImpl<MCFixup> &Fixups, |
403 | const MCSubtargetInfo &STI) const { |
404 | const MCOperand &MO = MI.getOperand(i: OpNo); |
405 | |
406 | // If the destination is an immediate, divide by 4. |
407 | if (MO.isImm()) return MO.getImm() >> 2; |
408 | |
409 | assert(MO.isExpr() && |
410 | "getBranchTarget21OpValueMM expects only expressions or immediates" ); |
411 | |
412 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
413 | LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx); |
414 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: FixupExpression, |
415 | Kind: MCFixupKind(Mips::fixup_MICROMIPS_PC21_S1))); |
416 | return 0; |
417 | } |
418 | |
419 | /// getBranchTarget26OpValue - Return binary encoding of the branch |
420 | /// target operand. If the machine operand requires relocation, |
421 | /// record the relocation and return zero. |
422 | unsigned MipsMCCodeEmitter:: |
423 | getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, |
424 | SmallVectorImpl<MCFixup> &Fixups, |
425 | const MCSubtargetInfo &STI) const { |
426 | const MCOperand &MO = MI.getOperand(i: OpNo); |
427 | |
428 | // If the destination is an immediate, divide by 4. |
429 | if (MO.isImm()) return MO.getImm() >> 2; |
430 | |
431 | assert(MO.isExpr() && |
432 | "getBranchTarget26OpValue expects only expressions or immediates" ); |
433 | |
434 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
435 | LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx); |
436 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: FixupExpression, |
437 | Kind: MCFixupKind(Mips::fixup_MIPS_PC26_S2))); |
438 | return 0; |
439 | } |
440 | |
441 | /// getBranchTarget26OpValueMM - Return binary encoding of the branch |
442 | /// target operand. If the machine operand requires relocation, |
443 | /// record the relocation and return zero. |
444 | unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM( |
445 | const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, |
446 | const MCSubtargetInfo &STI) const { |
447 | const MCOperand &MO = MI.getOperand(i: OpNo); |
448 | |
449 | // If the destination is an immediate, divide by 2. |
450 | if (MO.isImm()) |
451 | return MO.getImm() >> 1; |
452 | |
453 | assert(MO.isExpr() && |
454 | "getBranchTarget26OpValueMM expects only expressions or immediates" ); |
455 | |
456 | const MCExpr *FixupExpression = MCBinaryExpr::createAdd( |
457 | LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx); |
458 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: FixupExpression, |
459 | Kind: MCFixupKind(Mips::fixup_MICROMIPS_PC26_S1))); |
460 | return 0; |
461 | } |
462 | |
463 | /// getJumpOffset16OpValue - Return binary encoding of the jump |
464 | /// target operand. If the machine operand requires relocation, |
465 | /// record the relocation and return zero. |
466 | unsigned MipsMCCodeEmitter:: |
467 | getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo, |
468 | SmallVectorImpl<MCFixup> &Fixups, |
469 | const MCSubtargetInfo &STI) const { |
470 | const MCOperand &MO = MI.getOperand(i: OpNo); |
471 | |
472 | if (MO.isImm()) return MO.getImm(); |
473 | |
474 | assert(MO.isExpr() && |
475 | "getJumpOffset16OpValue expects only expressions or an immediate" ); |
476 | |
477 | const MCExpr *Expr = MO.getExpr(); |
478 | Mips::Fixups FixupKind = |
479 | isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 : Mips::fixup_Mips_LO16; |
480 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind))); |
481 | return 0; |
482 | } |
483 | |
484 | /// getJumpTargetOpValue - Return binary encoding of the jump |
485 | /// target operand. If the machine operand requires relocation, |
486 | /// record the relocation and return zero. |
487 | unsigned MipsMCCodeEmitter:: |
488 | getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, |
489 | SmallVectorImpl<MCFixup> &Fixups, |
490 | const MCSubtargetInfo &STI) const { |
491 | const MCOperand &MO = MI.getOperand(i: OpNo); |
492 | // If the destination is an immediate, divide by 4. |
493 | if (MO.isImm()) return MO.getImm()>>2; |
494 | |
495 | assert(MO.isExpr() && |
496 | "getJumpTargetOpValue expects only expressions or an immediate" ); |
497 | |
498 | const MCExpr *Expr = MO.getExpr(); |
499 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, |
500 | Kind: MCFixupKind(Mips::fixup_Mips_26))); |
501 | return 0; |
502 | } |
503 | |
504 | unsigned MipsMCCodeEmitter:: |
505 | getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, |
506 | SmallVectorImpl<MCFixup> &Fixups, |
507 | const MCSubtargetInfo &STI) const { |
508 | const MCOperand &MO = MI.getOperand(i: OpNo); |
509 | // If the destination is an immediate, divide by 2. |
510 | if (MO.isImm()) return MO.getImm() >> 1; |
511 | |
512 | assert(MO.isExpr() && |
513 | "getJumpTargetOpValueMM expects only expressions or an immediate" ); |
514 | |
515 | const MCExpr *Expr = MO.getExpr(); |
516 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, |
517 | Kind: MCFixupKind(Mips::fixup_MICROMIPS_26_S1))); |
518 | return 0; |
519 | } |
520 | |
521 | unsigned MipsMCCodeEmitter:: |
522 | getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, |
523 | SmallVectorImpl<MCFixup> &Fixups, |
524 | const MCSubtargetInfo &STI) const { |
525 | const MCOperand &MO = MI.getOperand(i: OpNo); |
526 | if (MO.isImm()) { |
527 | // The immediate is encoded as 'immediate << 2'. |
528 | unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); |
529 | assert((Res & 3) == 0); |
530 | return Res >> 2; |
531 | } |
532 | |
533 | assert(MO.isExpr() && |
534 | "getUImm5Lsl2Encoding expects only expressions or an immediate" ); |
535 | |
536 | return 0; |
537 | } |
538 | |
539 | unsigned MipsMCCodeEmitter:: |
540 | getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, |
541 | SmallVectorImpl<MCFixup> &Fixups, |
542 | const MCSubtargetInfo &STI) const { |
543 | const MCOperand &MO = MI.getOperand(i: OpNo); |
544 | if (MO.isImm()) { |
545 | int Value = MO.getImm(); |
546 | return Value >> 2; |
547 | } |
548 | |
549 | return 0; |
550 | } |
551 | |
552 | unsigned MipsMCCodeEmitter:: |
553 | getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, |
554 | SmallVectorImpl<MCFixup> &Fixups, |
555 | const MCSubtargetInfo &STI) const { |
556 | const MCOperand &MO = MI.getOperand(i: OpNo); |
557 | if (MO.isImm()) { |
558 | unsigned Value = MO.getImm(); |
559 | return Value >> 2; |
560 | } |
561 | |
562 | return 0; |
563 | } |
564 | |
565 | unsigned MipsMCCodeEmitter:: |
566 | getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, |
567 | SmallVectorImpl<MCFixup> &Fixups, |
568 | const MCSubtargetInfo &STI) const { |
569 | const MCOperand &MO = MI.getOperand(i: OpNo); |
570 | if (MO.isImm()) { |
571 | unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff; |
572 | return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff)); |
573 | } |
574 | |
575 | return 0; |
576 | } |
577 | |
578 | unsigned MipsMCCodeEmitter:: |
579 | getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, |
580 | const MCSubtargetInfo &STI) const { |
581 | int64_t Res; |
582 | |
583 | if (Expr->evaluateAsAbsolute(Res)) |
584 | return Res; |
585 | |
586 | MCExpr::ExprKind Kind = Expr->getKind(); |
587 | if (Kind == MCExpr::Constant) { |
588 | return cast<MCConstantExpr>(Val: Expr)->getValue(); |
589 | } |
590 | |
591 | if (Kind == MCExpr::Binary) { |
592 | unsigned Res = |
593 | getExprOpValue(Expr: cast<MCBinaryExpr>(Val: Expr)->getLHS(), Fixups, STI); |
594 | Res += getExprOpValue(Expr: cast<MCBinaryExpr>(Val: Expr)->getRHS(), Fixups, STI); |
595 | return Res; |
596 | } |
597 | |
598 | if (Kind == MCExpr::Target) { |
599 | const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Val: Expr); |
600 | |
601 | Mips::Fixups FixupKind = Mips::Fixups(0); |
602 | switch (MipsExpr->getKind()) { |
603 | case MipsMCExpr::MEK_None: |
604 | case MipsMCExpr::MEK_Special: |
605 | llvm_unreachable("Unhandled fixup kind!" ); |
606 | break; |
607 | case MipsMCExpr::MEK_DTPREL: |
608 | // MEK_DTPREL is used for marking TLS DIEExpr only |
609 | // and contains a regular sub-expression. |
610 | return getExprOpValue(Expr: MipsExpr->getSubExpr(), Fixups, STI); |
611 | case MipsMCExpr::MEK_CALL_HI16: |
612 | FixupKind = Mips::fixup_Mips_CALL_HI16; |
613 | break; |
614 | case MipsMCExpr::MEK_CALL_LO16: |
615 | FixupKind = Mips::fixup_Mips_CALL_LO16; |
616 | break; |
617 | case MipsMCExpr::MEK_DTPREL_HI: |
618 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 |
619 | : Mips::fixup_Mips_DTPREL_HI; |
620 | break; |
621 | case MipsMCExpr::MEK_DTPREL_LO: |
622 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 |
623 | : Mips::fixup_Mips_DTPREL_LO; |
624 | break; |
625 | case MipsMCExpr::MEK_GOTTPREL: |
626 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOTTPREL |
627 | : Mips::fixup_Mips_GOTTPREL; |
628 | break; |
629 | case MipsMCExpr::MEK_GOT: |
630 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 |
631 | : Mips::fixup_Mips_GOT; |
632 | break; |
633 | case MipsMCExpr::MEK_GOT_CALL: |
634 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16 |
635 | : Mips::fixup_Mips_CALL16; |
636 | break; |
637 | case MipsMCExpr::MEK_GOT_DISP: |
638 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP |
639 | : Mips::fixup_Mips_GOT_DISP; |
640 | break; |
641 | case MipsMCExpr::MEK_GOT_HI16: |
642 | FixupKind = Mips::fixup_Mips_GOT_HI16; |
643 | break; |
644 | case MipsMCExpr::MEK_GOT_LO16: |
645 | FixupKind = Mips::fixup_Mips_GOT_LO16; |
646 | break; |
647 | case MipsMCExpr::MEK_GOT_PAGE: |
648 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE |
649 | : Mips::fixup_Mips_GOT_PAGE; |
650 | break; |
651 | case MipsMCExpr::MEK_GOT_OFST: |
652 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST |
653 | : Mips::fixup_Mips_GOT_OFST; |
654 | break; |
655 | case MipsMCExpr::MEK_GPREL: |
656 | FixupKind = Mips::fixup_Mips_GPREL16; |
657 | break; |
658 | case MipsMCExpr::MEK_LO: |
659 | // Check for %lo(%neg(%gp_rel(X))) |
660 | if (MipsExpr->isGpOff()) |
661 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_LO |
662 | : Mips::fixup_Mips_GPOFF_LO; |
663 | else |
664 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 |
665 | : Mips::fixup_Mips_LO16; |
666 | break; |
667 | case MipsMCExpr::MEK_HIGHEST: |
668 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHEST |
669 | : Mips::fixup_Mips_HIGHEST; |
670 | break; |
671 | case MipsMCExpr::MEK_HIGHER: |
672 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHER |
673 | : Mips::fixup_Mips_HIGHER; |
674 | break; |
675 | case MipsMCExpr::MEK_HI: |
676 | // Check for %hi(%neg(%gp_rel(X))) |
677 | if (MipsExpr->isGpOff()) |
678 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_HI |
679 | : Mips::fixup_Mips_GPOFF_HI; |
680 | else |
681 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 |
682 | : Mips::fixup_Mips_HI16; |
683 | break; |
684 | case MipsMCExpr::MEK_PCREL_HI16: |
685 | FixupKind = Mips::fixup_MIPS_PCHI16; |
686 | break; |
687 | case MipsMCExpr::MEK_PCREL_LO16: |
688 | FixupKind = Mips::fixup_MIPS_PCLO16; |
689 | break; |
690 | case MipsMCExpr::MEK_TLSGD: |
691 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD |
692 | : Mips::fixup_Mips_TLSGD; |
693 | break; |
694 | case MipsMCExpr::MEK_TLSLDM: |
695 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM |
696 | : Mips::fixup_Mips_TLSLDM; |
697 | break; |
698 | case MipsMCExpr::MEK_TPREL_HI: |
699 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16 |
700 | : Mips::fixup_Mips_TPREL_HI; |
701 | break; |
702 | case MipsMCExpr::MEK_TPREL_LO: |
703 | FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 |
704 | : Mips::fixup_Mips_TPREL_LO; |
705 | break; |
706 | case MipsMCExpr::MEK_NEG: |
707 | FixupKind = |
708 | isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB; |
709 | break; |
710 | } |
711 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MipsExpr, Kind: MCFixupKind(FixupKind))); |
712 | return 0; |
713 | } |
714 | |
715 | if (Kind == MCExpr::SymbolRef) |
716 | Ctx.reportError(L: Expr->getLoc(), Msg: "expected an immediate" ); |
717 | return 0; |
718 | } |
719 | |
720 | /// getMachineOpValue - Return binary encoding of operand. If the machine |
721 | /// operand requires relocation, record the relocation and return zero. |
722 | unsigned MipsMCCodeEmitter:: |
723 | getMachineOpValue(const MCInst &MI, const MCOperand &MO, |
724 | SmallVectorImpl<MCFixup> &Fixups, |
725 | const MCSubtargetInfo &STI) const { |
726 | if (MO.isReg()) { |
727 | unsigned Reg = MO.getReg(); |
728 | unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(RegNo: Reg); |
729 | return RegNo; |
730 | } else if (MO.isImm()) { |
731 | return static_cast<unsigned>(MO.getImm()); |
732 | } else if (MO.isDFPImm()) { |
733 | return static_cast<unsigned>(bit_cast<double>(from: MO.getDFPImm())); |
734 | } |
735 | // MO must be an Expr. |
736 | assert(MO.isExpr()); |
737 | return getExprOpValue(Expr: MO.getExpr(),Fixups, STI); |
738 | } |
739 | |
740 | /// Return binary encoding of memory related operand. |
741 | /// If the offset operand requires relocation, record the relocation. |
742 | template <unsigned ShiftAmount> |
743 | unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, |
744 | SmallVectorImpl<MCFixup> &Fixups, |
745 | const MCSubtargetInfo &STI) const { |
746 | // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. |
747 | assert(MI.getOperand(OpNo).isReg()); |
748 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI) |
749 | << 16; |
750 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI); |
751 | |
752 | // Apply the scale factor if there is one. |
753 | OffBits >>= ShiftAmount; |
754 | |
755 | return (OffBits & 0xFFFF) | RegBits; |
756 | } |
757 | |
758 | unsigned MipsMCCodeEmitter:: |
759 | getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, |
760 | SmallVectorImpl<MCFixup> &Fixups, |
761 | const MCSubtargetInfo &STI) const { |
762 | // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. |
763 | assert(MI.getOperand(OpNo).isReg()); |
764 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), |
765 | Fixups, STI) << 4; |
766 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), |
767 | Fixups, STI); |
768 | |
769 | return (OffBits & 0xF) | RegBits; |
770 | } |
771 | |
772 | unsigned MipsMCCodeEmitter:: |
773 | getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, |
774 | SmallVectorImpl<MCFixup> &Fixups, |
775 | const MCSubtargetInfo &STI) const { |
776 | // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. |
777 | assert(MI.getOperand(OpNo).isReg()); |
778 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), |
779 | Fixups, STI) << 4; |
780 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), |
781 | Fixups, STI) >> 1; |
782 | |
783 | return (OffBits & 0xF) | RegBits; |
784 | } |
785 | |
786 | unsigned MipsMCCodeEmitter:: |
787 | getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, |
788 | SmallVectorImpl<MCFixup> &Fixups, |
789 | const MCSubtargetInfo &STI) const { |
790 | // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. |
791 | assert(MI.getOperand(OpNo).isReg()); |
792 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), |
793 | Fixups, STI) << 4; |
794 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), |
795 | Fixups, STI) >> 2; |
796 | |
797 | return (OffBits & 0xF) | RegBits; |
798 | } |
799 | |
800 | unsigned MipsMCCodeEmitter:: |
801 | getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, |
802 | SmallVectorImpl<MCFixup> &Fixups, |
803 | const MCSubtargetInfo &STI) const { |
804 | // Register is encoded in bits 9-5, offset is encoded in bits 4-0. |
805 | assert(MI.getOperand(OpNo).isReg() && |
806 | (MI.getOperand(OpNo).getReg() == Mips::SP || |
807 | MI.getOperand(OpNo).getReg() == Mips::SP_64) && |
808 | "Unexpected base register!" ); |
809 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), |
810 | Fixups, STI) >> 2; |
811 | |
812 | return OffBits & 0x1F; |
813 | } |
814 | |
815 | unsigned MipsMCCodeEmitter:: |
816 | getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, |
817 | SmallVectorImpl<MCFixup> &Fixups, |
818 | const MCSubtargetInfo &STI) const { |
819 | // Register is encoded in bits 9-7, offset is encoded in bits 6-0. |
820 | assert(MI.getOperand(OpNo).isReg() && |
821 | MI.getOperand(OpNo).getReg() == Mips::GP && |
822 | "Unexpected base register!" ); |
823 | |
824 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), |
825 | Fixups, STI) >> 2; |
826 | |
827 | return OffBits & 0x7F; |
828 | } |
829 | |
830 | unsigned MipsMCCodeEmitter:: |
831 | getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, |
832 | SmallVectorImpl<MCFixup> &Fixups, |
833 | const MCSubtargetInfo &STI) const { |
834 | // Base register is encoded in bits 20-16, offset is encoded in bits 8-0. |
835 | assert(MI.getOperand(OpNo).isReg()); |
836 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, |
837 | STI) << 16; |
838 | unsigned OffBits = |
839 | getMachineOpValue(MI, MO: MI.getOperand(i: OpNo + 1), Fixups, STI); |
840 | |
841 | return (OffBits & 0x1FF) | RegBits; |
842 | } |
843 | |
844 | unsigned MipsMCCodeEmitter:: |
845 | getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo, |
846 | SmallVectorImpl<MCFixup> &Fixups, |
847 | const MCSubtargetInfo &STI) const { |
848 | // Base register is encoded in bits 20-16, offset is encoded in bits 10-0. |
849 | assert(MI.getOperand(OpNo).isReg()); |
850 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, |
851 | STI) << 16; |
852 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI); |
853 | |
854 | return (OffBits & 0x07FF) | RegBits; |
855 | } |
856 | |
857 | unsigned MipsMCCodeEmitter:: |
858 | getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, |
859 | SmallVectorImpl<MCFixup> &Fixups, |
860 | const MCSubtargetInfo &STI) const { |
861 | // opNum can be invalid if instruction had reglist as operand. |
862 | // MemOperand is always last operand of instruction (base + offset). |
863 | switch (MI.getOpcode()) { |
864 | default: |
865 | break; |
866 | case Mips::SWM32_MM: |
867 | case Mips::LWM32_MM: |
868 | OpNo = MI.getNumOperands() - 2; |
869 | break; |
870 | } |
871 | |
872 | // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. |
873 | assert(MI.getOperand(OpNo).isReg()); |
874 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI) |
875 | << 16; |
876 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI); |
877 | |
878 | return (OffBits & 0x0FFF) | RegBits; |
879 | } |
880 | |
881 | unsigned MipsMCCodeEmitter:: |
882 | getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo, |
883 | SmallVectorImpl<MCFixup> &Fixups, |
884 | const MCSubtargetInfo &STI) const { |
885 | // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. |
886 | assert(MI.getOperand(OpNo).isReg()); |
887 | unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, |
888 | STI) << 16; |
889 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI); |
890 | |
891 | return (OffBits & 0xFFFF) | RegBits; |
892 | } |
893 | |
894 | unsigned MipsMCCodeEmitter:: |
895 | getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, |
896 | SmallVectorImpl<MCFixup> &Fixups, |
897 | const MCSubtargetInfo &STI) const { |
898 | // opNum can be invalid if instruction had reglist as operand |
899 | // MemOperand is always last operand of instruction (base + offset) |
900 | switch (MI.getOpcode()) { |
901 | default: |
902 | break; |
903 | case Mips::SWM16_MM: |
904 | case Mips::SWM16_MMR6: |
905 | case Mips::LWM16_MM: |
906 | case Mips::LWM16_MMR6: |
907 | OpNo = MI.getNumOperands() - 2; |
908 | break; |
909 | } |
910 | |
911 | // Offset is encoded in bits 4-0. |
912 | assert(MI.getOperand(OpNo).isReg()); |
913 | // Base register is always SP - thus it is not encoded. |
914 | assert(MI.getOperand(OpNo+1).isImm()); |
915 | unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI); |
916 | |
917 | return ((OffBits >> 2) & 0x0F); |
918 | } |
919 | |
920 | // FIXME: should be called getMSBEncoding |
921 | // |
922 | unsigned |
923 | MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, |
924 | SmallVectorImpl<MCFixup> &Fixups, |
925 | const MCSubtargetInfo &STI) const { |
926 | assert(MI.getOperand(OpNo-1).isImm()); |
927 | assert(MI.getOperand(OpNo).isImm()); |
928 | unsigned Position = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo-1), Fixups, STI); |
929 | unsigned Size = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI); |
930 | |
931 | return Position + Size - 1; |
932 | } |
933 | |
934 | template <unsigned Bits, int Offset> |
935 | unsigned |
936 | MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, |
937 | SmallVectorImpl<MCFixup> &Fixups, |
938 | const MCSubtargetInfo &STI) const { |
939 | assert(MI.getOperand(OpNo).isImm()); |
940 | unsigned Value = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI); |
941 | Value -= Offset; |
942 | return Value; |
943 | } |
944 | |
945 | unsigned |
946 | MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo, |
947 | SmallVectorImpl<MCFixup> &Fixups, |
948 | const MCSubtargetInfo &STI) const { |
949 | const MCOperand &MO = MI.getOperand(i: OpNo); |
950 | if (MO.isImm()) { |
951 | // The immediate is encoded as 'immediate << 2'. |
952 | unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); |
953 | assert((Res & 3) == 0); |
954 | return Res >> 2; |
955 | } |
956 | |
957 | assert(MO.isExpr() && |
958 | "getSimm19Lsl2Encoding expects only expressions or an immediate" ); |
959 | |
960 | const MCExpr *Expr = MO.getExpr(); |
961 | Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2 |
962 | : Mips::fixup_MIPS_PC19_S2; |
963 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind))); |
964 | return 0; |
965 | } |
966 | |
967 | unsigned |
968 | MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo, |
969 | SmallVectorImpl<MCFixup> &Fixups, |
970 | const MCSubtargetInfo &STI) const { |
971 | const MCOperand &MO = MI.getOperand(i: OpNo); |
972 | if (MO.isImm()) { |
973 | // The immediate is encoded as 'immediate << 3'. |
974 | unsigned Res = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI); |
975 | assert((Res & 7) == 0); |
976 | return Res >> 3; |
977 | } |
978 | |
979 | assert(MO.isExpr() && |
980 | "getSimm18Lsl2Encoding expects only expressions or an immediate" ); |
981 | |
982 | const MCExpr *Expr = MO.getExpr(); |
983 | Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3 |
984 | : Mips::fixup_MIPS_PC18_S3; |
985 | Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind))); |
986 | return 0; |
987 | } |
988 | |
989 | unsigned |
990 | MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, |
991 | SmallVectorImpl<MCFixup> &Fixups, |
992 | const MCSubtargetInfo &STI) const { |
993 | assert(MI.getOperand(OpNo).isImm()); |
994 | const MCOperand &MO = MI.getOperand(i: OpNo); |
995 | return MO.getImm() % 8; |
996 | } |
997 | |
998 | unsigned |
999 | MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo, |
1000 | SmallVectorImpl<MCFixup> &Fixups, |
1001 | const MCSubtargetInfo &STI) const { |
1002 | assert(MI.getOperand(OpNo).isImm()); |
1003 | const MCOperand &MO = MI.getOperand(i: OpNo); |
1004 | unsigned Value = MO.getImm(); |
1005 | switch (Value) { |
1006 | case 128: return 0x0; |
1007 | case 1: return 0x1; |
1008 | case 2: return 0x2; |
1009 | case 3: return 0x3; |
1010 | case 4: return 0x4; |
1011 | case 7: return 0x5; |
1012 | case 8: return 0x6; |
1013 | case 15: return 0x7; |
1014 | case 16: return 0x8; |
1015 | case 31: return 0x9; |
1016 | case 32: return 0xa; |
1017 | case 63: return 0xb; |
1018 | case 64: return 0xc; |
1019 | case 255: return 0xd; |
1020 | case 32768: return 0xe; |
1021 | case 65535: return 0xf; |
1022 | } |
1023 | llvm_unreachable("Unexpected value" ); |
1024 | } |
1025 | |
1026 | unsigned |
1027 | MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, |
1028 | SmallVectorImpl<MCFixup> &Fixups, |
1029 | const MCSubtargetInfo &STI) const { |
1030 | unsigned res = 0; |
1031 | |
1032 | // Register list operand is always first operand of instruction and it is |
1033 | // placed before memory operand (register + imm). |
1034 | |
1035 | for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) { |
1036 | unsigned Reg = MI.getOperand(i: I).getReg(); |
1037 | unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(RegNo: Reg); |
1038 | if (RegNo != 31) |
1039 | res++; |
1040 | else |
1041 | res |= 0x10; |
1042 | } |
1043 | return res; |
1044 | } |
1045 | |
1046 | unsigned |
1047 | MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, |
1048 | SmallVectorImpl<MCFixup> &Fixups, |
1049 | const MCSubtargetInfo &STI) const { |
1050 | return (MI.getNumOperands() - 4); |
1051 | } |
1052 | |
1053 | unsigned |
1054 | MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, |
1055 | SmallVectorImpl<MCFixup> &Fixups, |
1056 | const MCSubtargetInfo &STI) const { |
1057 | unsigned res = 0; |
1058 | |
1059 | if (MI.getOperand(i: 0).getReg() == Mips::A1 && |
1060 | MI.getOperand(i: 1).getReg() == Mips::A2) |
1061 | res = 0; |
1062 | else if (MI.getOperand(i: 0).getReg() == Mips::A1 && |
1063 | MI.getOperand(i: 1).getReg() == Mips::A3) |
1064 | res = 1; |
1065 | else if (MI.getOperand(i: 0).getReg() == Mips::A2 && |
1066 | MI.getOperand(i: 1).getReg() == Mips::A3) |
1067 | res = 2; |
1068 | else if (MI.getOperand(i: 0).getReg() == Mips::A0 && |
1069 | MI.getOperand(i: 1).getReg() == Mips::S5) |
1070 | res = 3; |
1071 | else if (MI.getOperand(i: 0).getReg() == Mips::A0 && |
1072 | MI.getOperand(i: 1).getReg() == Mips::S6) |
1073 | res = 4; |
1074 | else if (MI.getOperand(i: 0).getReg() == Mips::A0 && |
1075 | MI.getOperand(i: 1).getReg() == Mips::A1) |
1076 | res = 5; |
1077 | else if (MI.getOperand(i: 0).getReg() == Mips::A0 && |
1078 | MI.getOperand(i: 1).getReg() == Mips::A2) |
1079 | res = 6; |
1080 | else if (MI.getOperand(i: 0).getReg() == Mips::A0 && |
1081 | MI.getOperand(i: 1).getReg() == Mips::A3) |
1082 | res = 7; |
1083 | |
1084 | return res; |
1085 | } |
1086 | |
1087 | unsigned |
1088 | MipsMCCodeEmitter::getMovePRegSingleOpValue(const MCInst &MI, unsigned OpNo, |
1089 | SmallVectorImpl<MCFixup> &Fixups, |
1090 | const MCSubtargetInfo &STI) const { |
1091 | assert(((OpNo == 2) || (OpNo == 3)) && |
1092 | "Unexpected OpNo for movep operand encoding!" ); |
1093 | |
1094 | MCOperand Op = MI.getOperand(i: OpNo); |
1095 | assert(Op.isReg() && "Operand of movep is not a register!" ); |
1096 | switch (Op.getReg()) { |
1097 | default: |
1098 | llvm_unreachable("Unknown register for movep!" ); |
1099 | case Mips::ZERO: return 0; |
1100 | case Mips::S1: return 1; |
1101 | case Mips::V0: return 2; |
1102 | case Mips::V1: return 3; |
1103 | case Mips::S0: return 4; |
1104 | case Mips::S2: return 5; |
1105 | case Mips::S3: return 6; |
1106 | case Mips::S4: return 7; |
1107 | } |
1108 | } |
1109 | |
1110 | unsigned |
1111 | MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, |
1112 | SmallVectorImpl<MCFixup> &Fixups, |
1113 | const MCSubtargetInfo &STI) const { |
1114 | const MCOperand &MO = MI.getOperand(i: OpNo); |
1115 | assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate" ); |
1116 | // The immediate is encoded as 'immediate >> 2'. |
1117 | unsigned Res = static_cast<unsigned>(MO.getImm()); |
1118 | assert((Res & 3) == 0); |
1119 | return Res >> 2; |
1120 | } |
1121 | |
1122 | #include "MipsGenMCCodeEmitter.inc" |
1123 | |