blob: 0d74db808c38aa27f89e80481bdc90b0eb429560 [file] [log] [blame]
Jack Cartera7570a32012-09-06 02:31:34 +00001//===-- 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 "MipsDirectObjLower.h"
15#include "MipsInstrInfo.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 bool isLarge = false;
29 int64_t Shift;
30 Shift = Inst.getOperand(2).getImm();
31 if (Shift > 31) {
32 Shift -= 32;
33 isLarge = true;
34 }
35
36 // saminus32
37 (Inst.getOperand(2)).setImm(Shift);
38
39 if (isLarge)
40 switch (Inst.getOpcode()) {
41 default:
42 // Calling function is not synchronized
43 llvm_unreachable("Unexpected shift instruction");
44 case Mips::DSLL:
45 Inst.setOpcode(Mips::DSLL32);
46 return;
47 case Mips::DSRL:
48 Inst.setOpcode(Mips::DSRL32);
49 return;
50 case Mips::DSRA:
51 Inst.setOpcode(Mips::DSRA32);
52 return;
53 }
54}
55
56// Pick a DEXT or DINS instruction variant based on the pos and size operands
57void Mips::LowerDextDins(MCInst& InstIn) {
58 int Opcode = InstIn.getOpcode();
59
60 if (Opcode == Mips::DEXT)
61 assert(InstIn.getNumOperands() == 4 &&
62 "Invalid no. of machine operands for DEXT!");
63 else // Only DEXT and DINS are possible
64 assert(InstIn.getNumOperands() == 5 &&
65 "Invalid no. of machine operands for DINS!");
66
67 assert(InstIn.getOperand(2).isImm());
68 int64_t pos = InstIn.getOperand(2).getImm();
69 assert(InstIn.getOperand(3).isImm());
70 int64_t size = InstIn.getOperand(3).getImm();
71
72 if (size <= 32) {
73 if ((pos < 32)) { // DEXT/DINS, do nothing
74 return;
75 } else { // DEXTU/DINSU
76 InstIn.getOperand(2).setImm(pos - 32);
77 InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
78 return;
79 }
80 } else { // DEXTM/DINSM
81 assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
82 InstIn.getOperand(3).setImm(size - 32);
83 InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
84 return;
85 }
86}