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
19using 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
23void 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
53void 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}
82