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