mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-27 15:29:51 +00:00
If the code is generated as assembler, this transformation does not occur assuming that it will occur later in the assembler. This code was originally called from MipsAsmPrinter.cpp and we needed to check for OutStreamer.hasRawTextSupport(). This was not a good place for it and has been moved to MCTargetDesc/MipsMCCodeEmitter.cpp where both direct object and the assembler use it it automagically. The test cases have been checked in for a number of weeks now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165067 91177308-0d34-0410-b5e6-96231b3b80d8
82 lines
2.5 KiB
C++
82 lines
2.5 KiB
C++
//===-- MipsDirectObjLower.cpp - Mips LLVM direct object lowering -----===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains code to lower Mips MCInst records that are normally
|
|
// left to the assembler to lower such as large shifts.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "MipsInstrInfo.h"
|
|
#include "MCTargetDesc/MipsDirectObjLower.h"
|
|
#include "llvm/MC/MCInst.h"
|
|
#include "llvm/MC/MCStreamer.h"
|
|
|
|
using namespace llvm;
|
|
|
|
// If the D<shift> instruction has a shift amount that is greater
|
|
// than 31 (checked in calling routine), lower it to a D<shift>32 instruction
|
|
void Mips::LowerLargeShift(MCInst& Inst) {
|
|
|
|
assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
|
|
assert(Inst.getOperand(2).isImm());
|
|
|
|
int64_t Shift = Inst.getOperand(2).getImm();
|
|
if (Shift <= 31)
|
|
return; // Do nothing
|
|
Shift -= 32;
|
|
|
|
// saminus32
|
|
Inst.getOperand(2).setImm(Shift);
|
|
|
|
switch (Inst.getOpcode()) {
|
|
default:
|
|
// Calling function is not synchronized
|
|
llvm_unreachable("Unexpected shift instruction");
|
|
case Mips::DSLL:
|
|
Inst.setOpcode(Mips::DSLL32);
|
|
return;
|
|
case Mips::DSRL:
|
|
Inst.setOpcode(Mips::DSRL32);
|
|
return;
|
|
case Mips::DSRA:
|
|
Inst.setOpcode(Mips::DSRA32);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Pick a DEXT or DINS instruction variant based on the pos and size operands
|
|
void Mips::LowerDextDins(MCInst& InstIn) {
|
|
int Opcode = InstIn.getOpcode();
|
|
|
|
if (Opcode == Mips::DEXT)
|
|
assert(InstIn.getNumOperands() == 4 &&
|
|
"Invalid no. of machine operands for DEXT!");
|
|
else // Only DEXT and DINS are possible
|
|
assert(InstIn.getNumOperands() == 5 &&
|
|
"Invalid no. of machine operands for DINS!");
|
|
|
|
assert(InstIn.getOperand(2).isImm());
|
|
int64_t pos = InstIn.getOperand(2).getImm();
|
|
assert(InstIn.getOperand(3).isImm());
|
|
int64_t size = InstIn.getOperand(3).getImm();
|
|
|
|
if (size <= 32) {
|
|
if (pos < 32) // DEXT/DINS, do nothing
|
|
return;
|
|
// DEXTU/DINSU
|
|
InstIn.getOperand(2).setImm(pos - 32);
|
|
InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
|
|
return;
|
|
}
|
|
// DEXTM/DINSM
|
|
assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
|
|
InstIn.getOperand(3).setImm(size - 32);
|
|
InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
|
|
return;
|
|
}
|