Home | History | Annotate | Download | only in MCTargetDesc
      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 }
     82