]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsDirectObjLower.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / lib / Target / Mips / MCTargetDesc / MipsDirectObjLower.cpp
1 //===-- MipsDirectObjLower.cpp - Mips LLVM direct object lowering -----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains code to lower Mips MCInst records that are normally
11 // left to the assembler to lower such as large shifts.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "MipsInstrInfo.h"
15 #include "MCTargetDesc/MipsDirectObjLower.h"
16 #include "llvm/MC/MCInst.h"
17 #include "llvm/MC/MCStreamer.h"
18
19 using namespace llvm;
20
21 // If the D<shift> instruction has a shift amount that is greater
22 // than 31 (checked in calling routine), lower it to a D<shift>32 instruction
23 void Mips::LowerLargeShift(MCInst& Inst) {
24
25   assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
26   assert(Inst.getOperand(2).isImm());
27
28   int64_t Shift = Inst.getOperand(2).getImm();
29   if (Shift <= 31)
30     return; // Do nothing
31   Shift -= 32;
32
33   // saminus32
34   Inst.getOperand(2).setImm(Shift);
35
36   switch (Inst.getOpcode()) {
37   default:
38     // Calling function is not synchronized
39     llvm_unreachable("Unexpected shift instruction");
40   case Mips::DSLL:
41     Inst.setOpcode(Mips::DSLL32);
42     return;
43   case Mips::DSRL:
44     Inst.setOpcode(Mips::DSRL32);
45     return;
46   case Mips::DSRA:
47     Inst.setOpcode(Mips::DSRA32);
48     return;
49   }
50 }
51
52 // Pick a DEXT or DINS instruction variant based on the pos and size operands
53 void Mips::LowerDextDins(MCInst& InstIn) {
54   int Opcode = InstIn.getOpcode();
55
56   if (Opcode == Mips::DEXT)
57     assert(InstIn.getNumOperands() == 4 &&
58            "Invalid no. of machine operands for DEXT!");
59   else // Only DEXT and DINS are possible
60     assert(InstIn.getNumOperands() == 5 &&
61            "Invalid no. of machine operands for DINS!");
62
63   assert(InstIn.getOperand(2).isImm());
64   int64_t pos = InstIn.getOperand(2).getImm();
65   assert(InstIn.getOperand(3).isImm());
66   int64_t size = InstIn.getOperand(3).getImm();
67
68   if (size <= 32) {
69     if (pos < 32)  // DEXT/DINS, do nothing
70       return;
71     // DEXTU/DINSU
72     InstIn.getOperand(2).setImm(pos - 32);
73     InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
74     return;
75   }
76   // DEXTM/DINSM
77   assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
78   InstIn.getOperand(3).setImm(size - 32);
79   InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
80   return;
81 }