mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
generalize alias support to allow the result of an alias to
add fixed immediate values. Move the aad and aam aliases to use this, and document it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118350 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dea546b623
commit
98c870f87b
@ -1998,7 +1998,15 @@ def : InstAlias<"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg)>;
|
||||
<p>This example also shows that tied operands are only listed once. In the X86
|
||||
backend, XOR8rr has two input GR8's and one output GR8 (where an input is tied
|
||||
to the output). InstAliases take a flattened operand list without duplicates
|
||||
for tied operands.</p>
|
||||
for tied operands. The result of an instruction alias can also use immediates,
|
||||
which are added as simple immediate operands in the result, for example:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
def : InstAlias<"aad", (AAD8i8 10)>;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Instruction aliases can also have a Requires clause to make them
|
||||
subtarget specific.</p>
|
||||
|
@ -752,6 +752,22 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||
if (getLexer().is(AsmToken::EndOfStatement))
|
||||
Parser.Lex(); // Consume the EndOfStatement
|
||||
|
||||
// This is a terrible hack to handle "out[bwl]? %al, (%dx)" ->
|
||||
// "outb %al, %dx". Out doesn't take a memory form, but this is a widely
|
||||
// documented form in various unofficial manuals, so a lot of code uses it.
|
||||
if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
|
||||
Operands.size() == 3) {
|
||||
X86Operand &Op = *(X86Operand*)Operands.back();
|
||||
if (Op.isMem() && Op.Mem.SegReg == 0 &&
|
||||
isa<MCConstantExpr>(Op.Mem.Disp) &&
|
||||
cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
|
||||
Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
|
||||
SMLoc Loc = Op.getEndLoc();
|
||||
Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
|
||||
delete &Op;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to
|
||||
// "shift <op>".
|
||||
if ((Name.startswith("shr") || Name.startswith("sar") ||
|
||||
@ -781,20 +797,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||
X86Operand::CreateImm(One, NameLoc, NameLoc));
|
||||
}
|
||||
|
||||
// FIXME: Hack to handle "out[bwl]? %al, (%dx)" -> "outb %al, %dx".
|
||||
if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
|
||||
Operands.size() == 3) {
|
||||
X86Operand &Op = *(X86Operand*)Operands.back();
|
||||
if (Op.isMem() && Op.Mem.SegReg == 0 &&
|
||||
isa<MCConstantExpr>(Op.Mem.Disp) &&
|
||||
cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
|
||||
Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
|
||||
SMLoc Loc = Op.getEndLoc();
|
||||
Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
|
||||
delete &Op;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
|
||||
// "f{mul*,add*,sub*,div*} $op"
|
||||
if ((Name.startswith("fmul") || Name.startswith("fadd") ||
|
||||
@ -839,13 +841,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||
NameLoc, NameLoc));
|
||||
}
|
||||
|
||||
// FIXME: Hack to handle recognize "aa[dm]" -> "aa[dm] $0xA".
|
||||
if ((Name.startswith("aad") || Name.startswith("aam")) &&
|
||||
Operands.size() == 1) {
|
||||
const MCExpr *A = MCConstantExpr::Create(0xA, getParser().getContext());
|
||||
Operands.push_back(X86Operand::CreateImm(A, NameLoc, NameLoc));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1367,6 +1367,10 @@ defm : IntegerCondCodeMnemonicAlias<"cmov", "q">;
|
||||
// Assembler Instruction Aliases
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// aad/aam default to base 10 if no operand is specified.
|
||||
def : InstAlias<"aad", (AAD8i8 10)>;
|
||||
def : InstAlias<"aam", (AAM8i8 10)>;
|
||||
|
||||
// clr aliases.
|
||||
def : InstAlias<"clrb $reg", (XOR8rr GR8 :$reg, GR8 :$reg)>;
|
||||
def : InstAlias<"clrw $reg", (XOR16rr GR16:$reg, GR16:$reg)>;
|
||||
|
@ -270,7 +270,11 @@ struct MatchableInfo {
|
||||
|
||||
/// TiedOperand - This represents a result operand that is a duplicate of
|
||||
/// a previous result operand.
|
||||
TiedOperand
|
||||
TiedOperand,
|
||||
|
||||
/// ImmOperand - This represents an immediate value that is dumped into
|
||||
/// the operand.
|
||||
ImmOperand
|
||||
} Kind;
|
||||
|
||||
union {
|
||||
@ -281,6 +285,9 @@ struct MatchableInfo {
|
||||
/// TiedOperandNum - This is the (earlier) result operand that should be
|
||||
/// copied from.
|
||||
unsigned TiedOperandNum;
|
||||
|
||||
/// ImmVal - This is the immediate value added to the instruction.
|
||||
int64_t ImmVal;
|
||||
};
|
||||
|
||||
/// OpInfo - This is the information about the instruction operand that is
|
||||
@ -304,6 +311,15 @@ struct MatchableInfo {
|
||||
X.OpInfo = Op;
|
||||
return X;
|
||||
}
|
||||
|
||||
static ResOperand getImmOp(int64_t Val,
|
||||
const CGIOperandList::OperandInfo *Op) {
|
||||
ResOperand X;
|
||||
X.Kind = ImmOperand;
|
||||
X.ImmVal = Val;
|
||||
X.OpInfo = Op;
|
||||
return X;
|
||||
}
|
||||
};
|
||||
|
||||
/// TheDef - This is the definition of the instruction or InstAlias that this
|
||||
@ -538,16 +554,6 @@ void MatchableInfo::dump() {
|
||||
AsmOperand &Op = AsmOperands[i];
|
||||
errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
|
||||
errs() << '\"' << Op.Token << "\"\n";
|
||||
#if 0
|
||||
if (!Op.OperandInfo) {
|
||||
errs() << "(singleton register)\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
const CGIOperandList::OperandInfo &OI = *Op.OperandInfo;
|
||||
errs() << OI.Name << " " << OI.Rec->getName()
|
||||
<< " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1174,7 +1180,8 @@ void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II,
|
||||
|
||||
// Set up the operand class.
|
||||
for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)
|
||||
if (CGA.ResultOperands[i].Name == OperandName) {
|
||||
if (CGA.ResultOperands[i].isRecord() &&
|
||||
CGA.ResultOperands[i].getName() == OperandName) {
|
||||
// It's safe to go with the first one we find, because CodeGenInstAlias
|
||||
// validates that all operands with the same name have the same record.
|
||||
unsigned ResultIdx =CGA.getResultInstOperandIndexForResultOperandIndex(i);
|
||||
@ -1236,15 +1243,22 @@ void MatchableInfo::BuildAliasResultOperands() {
|
||||
|
||||
// Find out what operand from the asmparser that this MCInst operand comes
|
||||
// from.
|
||||
int SrcOperand = FindAsmOperandNamed(CGA.ResultOperands[AliasOpNo++].Name);
|
||||
if (SrcOperand != -1) {
|
||||
ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
|
||||
continue;
|
||||
if (CGA.ResultOperands[AliasOpNo].isRecord()) {
|
||||
StringRef Name = CGA.ResultOperands[AliasOpNo++].getName();
|
||||
int SrcOperand = FindAsmOperandNamed(Name);
|
||||
if (SrcOperand != -1) {
|
||||
ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
|
||||
continue;
|
||||
}
|
||||
|
||||
throw TGError(TheDef->getLoc(), "Instruction '" +
|
||||
TheDef->getName() + "' has operand '" + OpInfo.Name +
|
||||
"' that doesn't appear in asm string!");
|
||||
}
|
||||
|
||||
throw TGError(TheDef->getLoc(), "Instruction '" +
|
||||
TheDef->getName() + "' has operand '" + OpInfo.Name +
|
||||
"' that doesn't appear in asm string!");
|
||||
int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
|
||||
ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1291,7 +1305,6 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
|
||||
|
||||
// Generate code to populate each result operand.
|
||||
switch (OpInfo.Kind) {
|
||||
default: assert(0 && "Unknown result operand kind");
|
||||
case MatchableInfo::ResOperand::RenderAsmOperand: {
|
||||
// This comes from something we parsed.
|
||||
MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum];
|
||||
@ -1322,6 +1335,12 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
|
||||
Signature += "__Tie" + utostr(TiedOp);
|
||||
break;
|
||||
}
|
||||
case MatchableInfo::ResOperand::ImmOperand: {
|
||||
int64_t Val = OpInfo.ImmVal;
|
||||
CaseOS << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n";
|
||||
Signature += "__imm" + itostr(Val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,6 +449,21 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
|
||||
++AliasOpNo;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
|
||||
// Integer arguments can't have names.
|
||||
if (!Result->getArgName(AliasOpNo).empty())
|
||||
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
|
||||
" must not have a name!");
|
||||
if (ResultInst->Operands[i].MINumOperands != 1 ||
|
||||
!ResultInst->Operands[i].Rec->isSubClassOf("Operand"))
|
||||
throw TGError(R->getLoc(), "invalid argument class " +
|
||||
ResultInst->Operands[i].Rec->getName() +
|
||||
" for integer result operand!");
|
||||
ResultOperands.push_back(ResultOperand(II->getValue()));
|
||||
++AliasOpNo;
|
||||
continue;
|
||||
}
|
||||
|
||||
throw TGError(R->getLoc(), "result of inst alias has unknown operand type");
|
||||
}
|
||||
|
@ -267,10 +267,26 @@ namespace llvm {
|
||||
|
||||
|
||||
struct ResultOperand {
|
||||
private:
|
||||
StringRef Name;
|
||||
Record *R;
|
||||
|
||||
ResultOperand(StringRef N, Record *r) : Name(N), R(r) {}
|
||||
int64_t Imm;
|
||||
public:
|
||||
enum {
|
||||
K_Record,
|
||||
K_Imm
|
||||
} Kind;
|
||||
|
||||
ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {}
|
||||
ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
|
||||
|
||||
bool isRecord() const { return Kind == K_Record; }
|
||||
bool isImm() const { return Kind == K_Imm; }
|
||||
|
||||
StringRef getName() const { assert(isRecord()); return Name; }
|
||||
Record *getRecord() const { assert(isRecord()); return R; }
|
||||
int64_t getImm() const { assert(isImm()); return Imm; }
|
||||
};
|
||||
|
||||
/// ResultOperands - The decoded operands for the result instruction.
|
||||
|
Loading…
Reference in New Issue
Block a user