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 "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} 87