in llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp [1282:1988]
int HexagonAsmParser::processInstruction(MCInst &Inst,
OperandVector const &Operands,
SMLoc IDLoc) {
MCContext &Context = getParser().getContext();
const MCRegisterInfo *RI = getContext().getRegisterInfo();
const std::string r = "r";
const std::string v = "v";
const std::string Colon = ":";
using RegPairVals = std::pair<unsigned, unsigned>;
auto GetRegPair = [this, r](RegPairVals RegPair) {
const std::string R1 = r + utostr(RegPair.first);
const std::string R2 = r + utostr(RegPair.second);
return std::make_pair(matchRegister(R1), matchRegister(R2));
};
auto GetScalarRegs = [RI, GetRegPair](unsigned RegPair) {
const unsigned Lower = RI->getEncodingValue(RegPair);
const RegPairVals RegPair_ = std::make_pair(Lower + 1, Lower);
return GetRegPair(RegPair_);
};
auto GetVecRegs = [GetRegPair](unsigned VecRegPair) {
const RegPairVals RegPair =
HexagonMCInstrInfo::GetVecRegPairIndices(VecRegPair);
return GetRegPair(RegPair);
};
bool is32bit = false; // used to distinguish between CONST32 and CONST64
switch (Inst.getOpcode()) {
default:
if (HexagonMCInstrInfo::getDesc(MII, Inst).isPseudo()) {
SMDiagnostic Diag = getSourceManager().GetMessage(
IDLoc, SourceMgr::DK_Error,
"Found pseudo instruction with no expansion");
Diag.print("", errs());
report_fatal_error("Invalid pseudo instruction");
}
break;
case Hexagon::J2_trap1:
if (!getSTI().getFeatureBits()[Hexagon::ArchV65]) {
MCOperand &Rx = Inst.getOperand(0);
MCOperand &Ry = Inst.getOperand(1);
if (Rx.getReg() != Hexagon::R0 || Ry.getReg() != Hexagon::R0) {
Error(IDLoc, "trap1 can only have register r0 as operand");
return Match_InvalidOperand;
}
}
break;
case Hexagon::A2_iconst: {
Inst.setOpcode(Hexagon::A2_addi);
MCOperand Reg = Inst.getOperand(0);
MCOperand S27 = Inst.getOperand(1);
HexagonMCInstrInfo::setMustNotExtend(*S27.getExpr());
HexagonMCInstrInfo::setS27_2_reloc(*S27.getExpr());
Inst.clear();
Inst.addOperand(Reg);
Inst.addOperand(MCOperand::createReg(Hexagon::R0));
Inst.addOperand(S27);
break;
}
case Hexagon::M4_mpyrr_addr:
case Hexagon::S4_addi_asl_ri:
case Hexagon::S4_addi_lsr_ri:
case Hexagon::S4_andi_asl_ri:
case Hexagon::S4_andi_lsr_ri:
case Hexagon::S4_ori_asl_ri:
case Hexagon::S4_ori_lsr_ri:
case Hexagon::S4_or_andix:
case Hexagon::S4_subi_asl_ri:
case Hexagon::S4_subi_lsr_ri: {
MCOperand &Ry = Inst.getOperand(0);
MCOperand &src = Inst.getOperand(2);
if (RI->getEncodingValue(Ry.getReg()) != RI->getEncodingValue(src.getReg()))
return Match_InvalidOperand;
break;
}
case Hexagon::C2_cmpgei: {
MCOperand &MO = Inst.getOperand(2);
MO.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(MO.getExpr(),
MCConstantExpr::create(1, Context), Context),
Context));
Inst.setOpcode(Hexagon::C2_cmpgti);
break;
}
case Hexagon::C2_cmpgeui: {
MCOperand &MO = Inst.getOperand(2);
int64_t Value;
bool Success = MO.getExpr()->evaluateAsAbsolute(Value);
(void)Success;
assert(Success && "Assured by matcher");
if (Value == 0) {
MCInst TmpInst;
MCOperand &Pd = Inst.getOperand(0);
MCOperand &Rt = Inst.getOperand(1);
TmpInst.setOpcode(Hexagon::C2_cmpeq);
TmpInst.addOperand(Pd);
TmpInst.addOperand(Rt);
TmpInst.addOperand(Rt);
Inst = TmpInst;
} else {
MO.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(MO.getExpr(),
MCConstantExpr::create(1, Context), Context),
Context));
Inst.setOpcode(Hexagon::C2_cmpgtui);
}
break;
}
// Translate a "$Rdd = $Rss" to "$Rdd = combine($Rs, $Rt)"
case Hexagon::A2_tfrp: {
MCOperand &MO = Inst.getOperand(1);
const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
MO.setReg(RegPair.first);
Inst.addOperand(MCOperand::createReg(RegPair.second));
Inst.setOpcode(Hexagon::A2_combinew);
break;
}
case Hexagon::A2_tfrpt:
case Hexagon::A2_tfrpf: {
MCOperand &MO = Inst.getOperand(2);
const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
MO.setReg(RegPair.first);
Inst.addOperand(MCOperand::createReg(RegPair.second));
Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)
? Hexagon::C2_ccombinewt
: Hexagon::C2_ccombinewf);
break;
}
case Hexagon::A2_tfrptnew:
case Hexagon::A2_tfrpfnew: {
MCOperand &MO = Inst.getOperand(2);
const std::pair<unsigned, unsigned> RegPair = GetScalarRegs(MO.getReg());
MO.setReg(RegPair.first);
Inst.addOperand(MCOperand::createReg(RegPair.second));
Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew)
? Hexagon::C2_ccombinewnewt
: Hexagon::C2_ccombinewnewf);
break;
}
// Translate a "$Vdd = $Vss" to "$Vdd = vcombine($Vs, $Vt)"
case Hexagon::V6_vassignp: {
MCOperand &MO = Inst.getOperand(1);
const std::pair<unsigned, unsigned> RegPair = GetVecRegs(MO.getReg());
MO.setReg(RegPair.first);
Inst.addOperand(MCOperand::createReg(RegPair.second));
Inst.setOpcode(Hexagon::V6_vcombine);
break;
}
// Translate a "$Rx = CONST32(#imm)" to "$Rx = memw(gp+#LABEL) "
case Hexagon::CONST32:
is32bit = true;
LLVM_FALLTHROUGH;
// Translate a "$Rx:y = CONST64(#imm)" to "$Rx:y = memd(gp+#LABEL) "
case Hexagon::CONST64:
// FIXME: need better way to detect AsmStreamer (upstream removed getKind())
if (!Parser.getStreamer().hasRawTextSupport()) {
MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
MCOperand &MO_1 = Inst.getOperand(1);
MCOperand &MO_0 = Inst.getOperand(0);
// push section onto section stack
MES->PushSection();
std::string myCharStr;
MCSectionELF *mySection;
// check if this as an immediate or a symbol
int64_t Value;
bool Absolute = MO_1.getExpr()->evaluateAsAbsolute(Value);
if (Absolute) {
// Create a new section - one for each constant
// Some or all of the zeros are replaced with the given immediate.
if (is32bit) {
std::string myImmStr = utohexstr(static_cast<uint32_t>(Value));
myCharStr = StringRef(".gnu.linkonce.l4.CONST_00000000")
.drop_back(myImmStr.size())
.str() +
myImmStr;
} else {
std::string myImmStr = utohexstr(Value);
myCharStr = StringRef(".gnu.linkonce.l8.CONST_0000000000000000")
.drop_back(myImmStr.size())
.str() +
myImmStr;
}
mySection = getContext().getELFSection(myCharStr, ELF::SHT_PROGBITS,
ELF::SHF_ALLOC | ELF::SHF_WRITE);
} else if (MO_1.isExpr()) {
// .lita - for expressions
myCharStr = ".lita";
mySection = getContext().getELFSection(myCharStr, ELF::SHT_PROGBITS,
ELF::SHF_ALLOC | ELF::SHF_WRITE);
} else
llvm_unreachable("unexpected type of machine operand!");
MES->SwitchSection(mySection);
unsigned byteSize = is32bit ? 4 : 8;
getStreamer().emitCodeAlignment(byteSize, &getSTI(), byteSize);
MCSymbol *Sym;
// for symbols, get rid of prepended ".gnu.linkonce.lx."
// emit symbol if needed
if (Absolute) {
Sym = getContext().getOrCreateSymbol(StringRef(myCharStr.c_str() + 16));
if (Sym->isUndefined()) {
getStreamer().emitLabel(Sym);
getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
getStreamer().emitIntValue(Value, byteSize);
}
} else if (MO_1.isExpr()) {
const char *StringStart = nullptr;
const char *StringEnd = nullptr;
if (*Operands[4]->getStartLoc().getPointer() == '#') {
StringStart = Operands[5]->getStartLoc().getPointer();
StringEnd = Operands[6]->getStartLoc().getPointer();
} else { // no pound
StringStart = Operands[4]->getStartLoc().getPointer();
StringEnd = Operands[5]->getStartLoc().getPointer();
}
unsigned size = StringEnd - StringStart;
std::string DotConst = ".CONST_";
Sym = getContext().getOrCreateSymbol(DotConst +
StringRef(StringStart, size));
if (Sym->isUndefined()) {
// case where symbol is not yet defined: emit symbol
getStreamer().emitLabel(Sym);
getStreamer().emitSymbolAttribute(Sym, MCSA_Local);
getStreamer().emitValue(MO_1.getExpr(), 4);
}
} else
llvm_unreachable("unexpected type of machine operand!");
MES->PopSection();
if (Sym) {
MCInst TmpInst;
if (is32bit) // 32 bit
TmpInst.setOpcode(Hexagon::L2_loadrigp);
else // 64 bit
TmpInst.setOpcode(Hexagon::L2_loadrdgp);
TmpInst.addOperand(MO_0);
TmpInst.addOperand(MCOperand::createExpr(HexagonMCExpr::create(
MCSymbolRefExpr::create(Sym, getContext()), getContext())));
Inst = TmpInst;
}
}
break;
// Translate a "$Rdd = #-imm" to "$Rdd = combine(#[-1,0], #-imm)"
case Hexagon::A2_tfrpi: {
MCOperand &Rdd = Inst.getOperand(0);
MCOperand &MO = Inst.getOperand(1);
int64_t Value;
int sVal = (MO.getExpr()->evaluateAsAbsolute(Value) && Value < 0) ? -1 : 0;
MCOperand imm(MCOperand::createExpr(
HexagonMCExpr::create(MCConstantExpr::create(sVal, Context), Context)));
Inst = makeCombineInst(Hexagon::A2_combineii, Rdd, imm, MO);
break;
}
// Translate a "$Rdd = [#]#imm" to "$Rdd = combine(#, [#]#imm)"
case Hexagon::TFRI64_V4: {
MCOperand &Rdd = Inst.getOperand(0);
MCOperand &MO = Inst.getOperand(1);
int64_t Value;
if (MO.getExpr()->evaluateAsAbsolute(Value)) {
int s8 = Hi_32(Value);
if (!isInt<8>(s8))
OutOfRange(IDLoc, s8, -128);
MCOperand imm(MCOperand::createExpr(HexagonMCExpr::create(
MCConstantExpr::create(s8, Context), Context))); // upper 32
auto Expr = HexagonMCExpr::create(
MCConstantExpr::create(Lo_32(Value), Context), Context);
HexagonMCInstrInfo::setMustExtend(
*Expr, HexagonMCInstrInfo::mustExtend(*MO.getExpr()));
MCOperand imm2(MCOperand::createExpr(Expr)); // lower 32
Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, imm, imm2);
} else {
MCOperand imm(MCOperand::createExpr(HexagonMCExpr::create(
MCConstantExpr::create(0, Context), Context))); // upper 32
Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, imm, MO);
}
break;
}
// Handle $Rdd = combine(##imm, #imm)"
case Hexagon::TFRI64_V2_ext: {
MCOperand &Rdd = Inst.getOperand(0);
MCOperand &MO1 = Inst.getOperand(1);
MCOperand &MO2 = Inst.getOperand(2);
int64_t Value;
if (MO2.getExpr()->evaluateAsAbsolute(Value)) {
int s8 = Value;
if (s8 < -128 || s8 > 127)
OutOfRange(IDLoc, s8, -128);
}
Inst = makeCombineInst(Hexagon::A2_combineii, Rdd, MO1, MO2);
break;
}
// Handle $Rdd = combine(#imm, ##imm)"
case Hexagon::A4_combineii: {
MCOperand &Rdd = Inst.getOperand(0);
MCOperand &MO1 = Inst.getOperand(1);
int64_t Value;
if (MO1.getExpr()->evaluateAsAbsolute(Value)) {
int s8 = Value;
if (s8 < -128 || s8 > 127)
OutOfRange(IDLoc, s8, -128);
}
MCOperand &MO2 = Inst.getOperand(2);
Inst = makeCombineInst(Hexagon::A4_combineii, Rdd, MO1, MO2);
break;
}
case Hexagon::S2_tableidxb_goodsyntax:
Inst.setOpcode(Hexagon::S2_tableidxb);
break;
case Hexagon::S2_tableidxh_goodsyntax: {
MCInst TmpInst;
MCOperand &Rx = Inst.getOperand(0);
MCOperand &Rs = Inst.getOperand(2);
MCOperand &Imm4 = Inst.getOperand(3);
MCOperand &Imm6 = Inst.getOperand(4);
Imm6.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(Imm6.getExpr(),
MCConstantExpr::create(1, Context), Context),
Context));
TmpInst.setOpcode(Hexagon::S2_tableidxh);
TmpInst.addOperand(Rx);
TmpInst.addOperand(Rx);
TmpInst.addOperand(Rs);
TmpInst.addOperand(Imm4);
TmpInst.addOperand(Imm6);
Inst = TmpInst;
break;
}
case Hexagon::S2_tableidxw_goodsyntax: {
MCInst TmpInst;
MCOperand &Rx = Inst.getOperand(0);
MCOperand &Rs = Inst.getOperand(2);
MCOperand &Imm4 = Inst.getOperand(3);
MCOperand &Imm6 = Inst.getOperand(4);
Imm6.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(Imm6.getExpr(),
MCConstantExpr::create(2, Context), Context),
Context));
TmpInst.setOpcode(Hexagon::S2_tableidxw);
TmpInst.addOperand(Rx);
TmpInst.addOperand(Rx);
TmpInst.addOperand(Rs);
TmpInst.addOperand(Imm4);
TmpInst.addOperand(Imm6);
Inst = TmpInst;
break;
}
case Hexagon::S2_tableidxd_goodsyntax: {
MCInst TmpInst;
MCOperand &Rx = Inst.getOperand(0);
MCOperand &Rs = Inst.getOperand(2);
MCOperand &Imm4 = Inst.getOperand(3);
MCOperand &Imm6 = Inst.getOperand(4);
Imm6.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(Imm6.getExpr(),
MCConstantExpr::create(3, Context), Context),
Context));
TmpInst.setOpcode(Hexagon::S2_tableidxd);
TmpInst.addOperand(Rx);
TmpInst.addOperand(Rx);
TmpInst.addOperand(Rs);
TmpInst.addOperand(Imm4);
TmpInst.addOperand(Imm6);
Inst = TmpInst;
break;
}
case Hexagon::M2_mpyui:
Inst.setOpcode(Hexagon::M2_mpyi);
break;
case Hexagon::M2_mpysmi: {
MCInst TmpInst;
MCOperand &Rd = Inst.getOperand(0);
MCOperand &Rs = Inst.getOperand(1);
MCOperand &Imm = Inst.getOperand(2);
int64_t Value;
MCExpr const &Expr = *Imm.getExpr();
bool Absolute = Expr.evaluateAsAbsolute(Value);
if (!Absolute)
return Match_InvalidOperand;
if (!HexagonMCInstrInfo::mustExtend(Expr) &&
((Value <= -256) || Value >= 256))
return Match_InvalidOperand;
if (Value < 0 && Value > -256) {
Imm.setExpr(HexagonMCExpr::create(
MCConstantExpr::create(Value * -1, Context), Context));
TmpInst.setOpcode(Hexagon::M2_mpysin);
} else
TmpInst.setOpcode(Hexagon::M2_mpysip);
TmpInst.addOperand(Rd);
TmpInst.addOperand(Rs);
TmpInst.addOperand(Imm);
Inst = TmpInst;
break;
}
case Hexagon::S2_asr_i_r_rnd_goodsyntax: {
MCOperand &Imm = Inst.getOperand(2);
MCInst TmpInst;
int64_t Value;
bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
if (!Absolute)
return Match_InvalidOperand;
if (Value == 0) { // convert to $Rd = $Rs
TmpInst.setOpcode(Hexagon::A2_tfr);
MCOperand &Rd = Inst.getOperand(0);
MCOperand &Rs = Inst.getOperand(1);
TmpInst.addOperand(Rd);
TmpInst.addOperand(Rs);
} else {
Imm.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(Imm.getExpr(),
MCConstantExpr::create(1, Context), Context),
Context));
TmpInst.setOpcode(Hexagon::S2_asr_i_r_rnd);
MCOperand &Rd = Inst.getOperand(0);
MCOperand &Rs = Inst.getOperand(1);
TmpInst.addOperand(Rd);
TmpInst.addOperand(Rs);
TmpInst.addOperand(Imm);
}
Inst = TmpInst;
break;
}
case Hexagon::S2_asr_i_p_rnd_goodsyntax: {
MCOperand &Rdd = Inst.getOperand(0);
MCOperand &Rss = Inst.getOperand(1);
MCOperand &Imm = Inst.getOperand(2);
int64_t Value;
bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
if (!Absolute)
return Match_InvalidOperand;
if (Value == 0) { // convert to $Rdd = combine ($Rs[0], $Rs[1])
MCInst TmpInst;
unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg());
std::string R1 = r + utostr(RegPairNum + 1);
StringRef Reg1(R1);
Rss.setReg(matchRegister(Reg1));
// Add a new operand for the second register in the pair.
std::string R2 = r + utostr(RegPairNum);
StringRef Reg2(R2);
TmpInst.setOpcode(Hexagon::A2_combinew);
TmpInst.addOperand(Rdd);
TmpInst.addOperand(Rss);
TmpInst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
Inst = TmpInst;
} else {
Imm.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(Imm.getExpr(),
MCConstantExpr::create(1, Context), Context),
Context));
Inst.setOpcode(Hexagon::S2_asr_i_p_rnd);
}
break;
}
case Hexagon::A4_boundscheck: {
MCOperand &Rs = Inst.getOperand(1);
unsigned int RegNum = RI->getEncodingValue(Rs.getReg());
if (RegNum & 1) { // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
Inst.setOpcode(Hexagon::A4_boundscheck_hi);
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
StringRef RegPair = Name;
Rs.setReg(matchRegister(RegPair));
} else { // raw:lo
Inst.setOpcode(Hexagon::A4_boundscheck_lo);
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
StringRef RegPair = Name;
Rs.setReg(matchRegister(RegPair));
}
break;
}
case Hexagon::A2_addsp: {
MCOperand &Rs = Inst.getOperand(1);
unsigned int RegNum = RI->getEncodingValue(Rs.getReg());
if (RegNum & 1) { // Odd mapped to raw:hi
Inst.setOpcode(Hexagon::A2_addsph);
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
StringRef RegPair = Name;
Rs.setReg(matchRegister(RegPair));
} else { // Even mapped raw:lo
Inst.setOpcode(Hexagon::A2_addspl);
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
StringRef RegPair = Name;
Rs.setReg(matchRegister(RegPair));
}
break;
}
case Hexagon::M2_vrcmpys_s1: {
MCOperand &Rt = Inst.getOperand(2);
unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
if (RegNum & 1) { // Odd mapped to sat:raw:hi
Inst.setOpcode(Hexagon::M2_vrcmpys_s1_h);
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
StringRef RegPair = Name;
Rt.setReg(matchRegister(RegPair));
} else { // Even mapped sat:raw:lo
Inst.setOpcode(Hexagon::M2_vrcmpys_s1_l);
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
StringRef RegPair = Name;
Rt.setReg(matchRegister(RegPair));
}
break;
}
case Hexagon::M2_vrcmpys_acc_s1: {
MCInst TmpInst;
MCOperand &Rxx = Inst.getOperand(0);
MCOperand &Rss = Inst.getOperand(2);
MCOperand &Rt = Inst.getOperand(3);
unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
if (RegNum & 1) { // Odd mapped to sat:raw:hi
TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
StringRef RegPair = Name;
Rt.setReg(matchRegister(RegPair));
} else { // Even mapped sat:raw:lo
TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
StringRef RegPair = Name;
Rt.setReg(matchRegister(RegPair));
}
// Registers are in different positions
TmpInst.addOperand(Rxx);
TmpInst.addOperand(Rxx);
TmpInst.addOperand(Rss);
TmpInst.addOperand(Rt);
Inst = TmpInst;
break;
}
case Hexagon::M2_vrcmpys_s1rp: {
MCOperand &Rt = Inst.getOperand(2);
unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
if (RegNum & 1) { // Odd mapped to rnd:sat:raw:hi
Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
StringRef RegPair = Name;
Rt.setReg(matchRegister(RegPair));
} else { // Even mapped rnd:sat:raw:lo
Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
StringRef RegPair = Name;
Rt.setReg(matchRegister(RegPair));
}
break;
}
case Hexagon::S5_asrhub_rnd_sat_goodsyntax: {
MCOperand &Imm = Inst.getOperand(2);
int64_t Value;
bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
if (!Absolute)
return Match_InvalidOperand;
if (Value == 0)
Inst.setOpcode(Hexagon::S2_vsathub);
else {
Imm.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(Imm.getExpr(),
MCConstantExpr::create(1, Context), Context),
Context));
Inst.setOpcode(Hexagon::S5_asrhub_rnd_sat);
}
break;
}
case Hexagon::S5_vasrhrnd_goodsyntax: {
MCOperand &Rdd = Inst.getOperand(0);
MCOperand &Rss = Inst.getOperand(1);
MCOperand &Imm = Inst.getOperand(2);
int64_t Value;
bool Absolute = Imm.getExpr()->evaluateAsAbsolute(Value);
if (!Absolute)
return Match_InvalidOperand;
if (Value == 0) {
MCInst TmpInst;
unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg());
std::string R1 = r + utostr(RegPairNum + 1);
StringRef Reg1(R1);
Rss.setReg(matchRegister(Reg1));
// Add a new operand for the second register in the pair.
std::string R2 = r + utostr(RegPairNum);
StringRef Reg2(R2);
TmpInst.setOpcode(Hexagon::A2_combinew);
TmpInst.addOperand(Rdd);
TmpInst.addOperand(Rss);
TmpInst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
Inst = TmpInst;
} else {
Imm.setExpr(HexagonMCExpr::create(
MCBinaryExpr::createSub(Imm.getExpr(),
MCConstantExpr::create(1, Context), Context),
Context));
Inst.setOpcode(Hexagon::S5_vasrhrnd);
}
break;
}
case Hexagon::A2_not: {
MCInst TmpInst;
MCOperand &Rd = Inst.getOperand(0);
MCOperand &Rs = Inst.getOperand(1);
TmpInst.setOpcode(Hexagon::A2_subri);
TmpInst.addOperand(Rd);
TmpInst.addOperand(MCOperand::createExpr(
HexagonMCExpr::create(MCConstantExpr::create(-1, Context), Context)));
TmpInst.addOperand(Rs);
Inst = TmpInst;
break;
}
case Hexagon::PS_loadrubabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
Inst.setOpcode(Hexagon::L2_loadrubgp);
break;
case Hexagon::PS_loadrbabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
Inst.setOpcode(Hexagon::L2_loadrbgp);
break;
case Hexagon::PS_loadruhabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
Inst.setOpcode(Hexagon::L2_loadruhgp);
break;
case Hexagon::PS_loadrhabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
Inst.setOpcode(Hexagon::L2_loadrhgp);
break;
case Hexagon::PS_loadriabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
Inst.setOpcode(Hexagon::L2_loadrigp);
break;
case Hexagon::PS_loadrdabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(1).getExpr()))
Inst.setOpcode(Hexagon::L2_loadrdgp);
break;
case Hexagon::PS_storerbabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
Inst.setOpcode(Hexagon::S2_storerbgp);
break;
case Hexagon::PS_storerhabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
Inst.setOpcode(Hexagon::S2_storerhgp);
break;
case Hexagon::PS_storerfabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
Inst.setOpcode(Hexagon::S2_storerfgp);
break;
case Hexagon::PS_storeriabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
Inst.setOpcode(Hexagon::S2_storerigp);
break;
case Hexagon::PS_storerdabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
Inst.setOpcode(Hexagon::S2_storerdgp);
break;
case Hexagon::PS_storerbnewabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
Inst.setOpcode(Hexagon::S2_storerbnewgp);
break;
case Hexagon::PS_storerhnewabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
Inst.setOpcode(Hexagon::S2_storerhnewgp);
break;
case Hexagon::PS_storerinewabs:
if (!HexagonMCInstrInfo::mustExtend(*Inst.getOperand(0).getExpr()))
Inst.setOpcode(Hexagon::S2_storerinewgp);
break;
case Hexagon::A2_zxtb: {
Inst.setOpcode(Hexagon::A2_andir);
Inst.addOperand(
MCOperand::createExpr(MCConstantExpr::create(255, Context)));
break;
}
} // switch
return Match_Success;
}