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