mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-02 22:23:10 +00:00
[mips] Implementation of dli.
Patch by David Chisnall
His work was sponsored by: DARPA, AFRL
Some small modifications to the original patch: we now error if
it's not possible to expand an instruction (mips-expansions-bad.s has some
examples). Added some comments to the expansions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211271 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -984,6 +984,7 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) {
|
||||
case Mips::LoadImm32Reg:
|
||||
case Mips::LoadAddr32Imm:
|
||||
case Mips::LoadAddr32Reg:
|
||||
case Mips::LoadImm64Reg:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -997,6 +998,12 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
return true;
|
||||
case Mips::LoadImm32Reg:
|
||||
return expandLoadImm(Inst, IDLoc, Instructions);
|
||||
case Mips::LoadImm64Reg:
|
||||
if (!isGP64()) {
|
||||
Error(IDLoc, "instruction requires a CPU feature not currently enabled");
|
||||
return true;
|
||||
}
|
||||
return expandLoadImm(Inst, IDLoc, Instructions);
|
||||
case Mips::LoadAddr32Imm:
|
||||
return expandLoadAddressImm(Inst, IDLoc, Instructions);
|
||||
case Mips::LoadAddr32Reg:
|
||||
@@ -1004,6 +1011,30 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <int Shift, bool PerformShift>
|
||||
void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions) {
|
||||
MCInst tmpInst;
|
||||
if (PerformShift) {
|
||||
tmpInst.setOpcode(Mips::DSLL);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegNo));
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegNo));
|
||||
tmpInst.addOperand(MCOperand::CreateImm(16));
|
||||
tmpInst.setLoc(IDLoc);
|
||||
Instructions.push_back(tmpInst);
|
||||
tmpInst.clear();
|
||||
}
|
||||
tmpInst.setOpcode(Mips::ORi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegNo));
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegNo));
|
||||
tmpInst.addOperand(
|
||||
MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)));
|
||||
tmpInst.setLoc(IDLoc);
|
||||
Instructions.push_back(tmpInst);
|
||||
}
|
||||
}
|
||||
|
||||
bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &Instructions) {
|
||||
MCInst tmpInst;
|
||||
@@ -1012,8 +1043,10 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
||||
const MCOperand &RegOp = Inst.getOperand(0);
|
||||
assert(RegOp.isReg() && "expected register operand kind");
|
||||
|
||||
int ImmValue = ImmOp.getImm();
|
||||
int64_t ImmValue = ImmOp.getImm();
|
||||
tmpInst.setLoc(IDLoc);
|
||||
// FIXME: gas has a special case for values that are 000...1111, which
|
||||
// becomes a li -1 and then a dsrl
|
||||
if (0 <= ImmValue && ImmValue <= 65535) {
|
||||
// For 0 <= j <= 65535.
|
||||
// li d,j => ori d,$zero,j
|
||||
@@ -1030,21 +1063,71 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
||||
tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
|
||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
||||
Instructions.push_back(tmpInst);
|
||||
} else {
|
||||
// For any other value of j that is representable as a 32-bit integer.
|
||||
} else if ((ImmValue & 0xffffffff) == ImmValue) {
|
||||
// For any value of j that is representable as a 32-bit integer, create
|
||||
// a sequence of:
|
||||
// li d,j => lui d,hi16(j)
|
||||
// ori d,d,lo16(j)
|
||||
tmpInst.setOpcode(Mips::LUi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
||||
Instructions.push_back(tmpInst);
|
||||
tmpInst.clear();
|
||||
tmpInst.setOpcode(Mips::ORi);
|
||||
createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
|
||||
} else if ((ImmValue & (0xffffLL << 48)) == 0) {
|
||||
if (!isGP64()) {
|
||||
Error (IDLoc, "instruction requires a CPU feature not currently enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
// <------- lo32 ------>
|
||||
// <------- hi32 ------>
|
||||
// <- hi16 -> <- lo16 ->
|
||||
// _________________________________
|
||||
// | | | |
|
||||
// | 16-bytes | 16-bytes | 16-bytes |
|
||||
// |__________|__________|__________|
|
||||
//
|
||||
// For any value of j that is representable as a 48-bit integer, create
|
||||
// a sequence of:
|
||||
// li d,j => lui d,hi16(j)
|
||||
// ori d,d,hi16(lo32(j))
|
||||
// dsll d,d,16
|
||||
// ori d,d,lo16(lo32(j))
|
||||
tmpInst.setOpcode(Mips::LUi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
||||
tmpInst.setLoc(IDLoc);
|
||||
tmpInst.addOperand(
|
||||
MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
|
||||
Instructions.push_back(tmpInst);
|
||||
createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
|
||||
createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
|
||||
} else {
|
||||
if (!isGP64()) {
|
||||
Error (IDLoc, "instruction requires a CPU feature not currently enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
// <------- hi32 ------> <------- lo32 ------>
|
||||
// <- hi16 -> <- lo16 ->
|
||||
// ___________________________________________
|
||||
// | | | | |
|
||||
// | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
|
||||
// |__________|__________|__________|__________|
|
||||
//
|
||||
// For any value of j that isn't representable as a 48-bit integer.
|
||||
// li d,j => lui d,hi16(j)
|
||||
// ori d,d,lo16(hi32(j))
|
||||
// dsll d,d,16
|
||||
// ori d,d,hi16(lo32(j))
|
||||
// dsll d,d,16
|
||||
// ori d,d,lo16(lo32(j))
|
||||
tmpInst.setOpcode(Mips::LUi);
|
||||
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
||||
tmpInst.addOperand(
|
||||
MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
|
||||
Instructions.push_back(tmpInst);
|
||||
createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
|
||||
createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
|
||||
createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user