Skip to content

Commit 68806b9

Browse files
authored
[Xtensa] Implement SEXT, NSA, MINMAX and Loop Xtensa Options. (#133818)
Implement basic support of the several simple Xtensa Options with 1-4 instructions for each option. The Sign Extend Option (SEXT). The NSA Option. The Minimum/Maximum Integer 32-bit Option and Loop Option. Fixed address operands, added OPERAND_PCREL to operands descriptions.
1 parent 1bcec03 commit 68806b9

24 files changed

+512
-61
lines changed

llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ struct XtensaOperand : public MCParsedAsmOperand {
273273
return false;
274274
}
275275

276+
bool isimm7_22() const { return isImm(7, 22); }
277+
276278
/// getStartLoc - Gets location of the first token of this operand
277279
SMLoc getStartLoc() const override { return StartLoc; }
278280
/// getEndLoc - Gets location of the last token of this operand
@@ -538,6 +540,9 @@ bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
538540
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
539541
"expected immediate in range [0, 32760], first 3 bits "
540542
"should be zero");
543+
case Match_Invalidimm7_22:
544+
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
545+
"expected immediate in range [7, 22]");
541546
}
542547

543548
report_fatal_error("Unknown match type detected!");

llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
168168
static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm,
169169
int64_t Address, const void *Decoder) {
170170
assert(isUInt<18>(Imm) && "Invalid immediate");
171-
Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2)));
171+
Inst.addOperand(
172+
MCOperand::createImm(SignExtend64<20>(Imm << 2) + (Address & 0x3)));
172173
return MCDisassembler::Success;
173174
}
174175

@@ -200,6 +201,16 @@ static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm,
200201
return MCDisassembler::Success;
201202
}
202203

204+
static DecodeStatus decodeLoopOperand(MCInst &Inst, uint64_t Imm,
205+
int64_t Address, const void *Decoder) {
206+
207+
assert(isUInt<8>(Imm) && "Invalid immediate");
208+
if (!tryAddingSymbolicOperand(Imm + 4 + Address, true, Address, 0, 3, Inst,
209+
Decoder))
210+
Inst.addOperand(MCOperand::createImm(Imm));
211+
return MCDisassembler::Success;
212+
}
213+
203214
static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm,
204215
int64_t Address, const void *Decoder) {
205216

@@ -326,6 +337,13 @@ static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm,
326337
return MCDisassembler::Success;
327338
}
328339

340+
static DecodeStatus decodeImm7_22Operand(MCInst &Inst, uint64_t Imm,
341+
int64_t Address, const void *Decoder) {
342+
assert(isUInt<4>(Imm) && "Invalid immediate");
343+
Inst.addOperand(MCOperand::createImm(Imm + 7));
344+
return MCDisassembler::Success;
345+
}
346+
329347
static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm,
330348
int64_t Address, const void *Decoder) {
331349
assert(isUInt<12>(Imm) && "Invalid immediate");

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ XtensaMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
6464
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
6565
{"fixup_xtensa_l32r_16", 8, 16,
6666
MCFixupKindInfo::FKF_IsPCRel |
67-
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}};
67+
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
68+
{"fixup_xtensa_loop_8", 16, 8, MCFixupKindInfo::FKF_IsPCRel}};
6869

6970
if (Kind < FirstTargetFixupKind)
7071
return MCAsmBackend::getFixupKindInfo(Kind);
@@ -116,6 +117,11 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
116117
if (Value & 0x3)
117118
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
118119
return (Value & 0xffffc) >> 2;
120+
case Xtensa::fixup_xtensa_loop_8:
121+
Value -= 4;
122+
if (!isUInt<8>(Value))
123+
Ctx.reportError(Fixup.getLoc(), "loop fixup value out of range");
124+
return (Value & 0xff);
119125
case Xtensa::fixup_xtensa_l32r_16:
120126
unsigned Offset = Fixup.getOffset();
121127
if (Offset & 0x3)

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaFixupKinds.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum FixupKind {
2222
fixup_xtensa_jump_18,
2323
fixup_xtensa_call_18,
2424
fixup_xtensa_l32r_16,
25+
fixup_xtensa_loop_8,
2526
fixup_xtensa_invalid,
2627
LastTargetFixupKind,
2728
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp

Lines changed: 74 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -90,70 +90,103 @@ void XtensaInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
9090
printOperand(MI, OpNum + 1, OS);
9191
}
9292

93-
void XtensaInstPrinter::printBranchTarget(const MCInst *MI, int OpNum,
94-
raw_ostream &OS) {
93+
void XtensaInstPrinter::printBranchTarget(const MCInst *MI, uint64_t Address,
94+
int OpNum, raw_ostream &O) {
9595
const MCOperand &MC = MI->getOperand(OpNum);
9696
if (MI->getOperand(OpNum).isImm()) {
9797
int64_t Val = MC.getImm() + 4;
98-
OS << ". ";
99-
if (Val > 0)
100-
OS << '+';
101-
OS << Val;
98+
printPCRelImm(Address, Val, O);
10299
} else if (MC.isExpr())
103-
MC.getExpr()->print(OS, &MAI);
100+
MC.getExpr()->print(O, &MAI);
104101
else
105102
llvm_unreachable("Invalid operand");
106103
}
107104

108-
void XtensaInstPrinter::printJumpTarget(const MCInst *MI, int OpNum,
109-
raw_ostream &OS) {
105+
void XtensaInstPrinter::printLoopTarget(const MCInst *MI, uint64_t Address,
106+
int OpNum, raw_ostream &O) {
107+
const MCOperand &MC = MI->getOperand(OpNum);
108+
if (MI->getOperand(OpNum).isImm()) {
109+
int64_t Val = MC.getImm() + 4;
110+
printPCRelImm(Address, Val, O);
111+
} else if (MC.isExpr())
112+
MC.getExpr()->print(O, &MAI, true);
113+
else
114+
llvm_unreachable("Invalid operand");
115+
}
116+
117+
void XtensaInstPrinter::printJumpTarget(const MCInst *MI, uint64_t Address,
118+
int OpNum, raw_ostream &O) {
110119
const MCOperand &MC = MI->getOperand(OpNum);
111120
if (MC.isImm()) {
112121
int64_t Val = MC.getImm() + 4;
113-
OS << ". ";
114-
if (Val > 0)
115-
OS << '+';
116-
OS << Val;
122+
printPCRelImm(Address, Val, O);
117123
} else if (MC.isExpr())
118-
MC.getExpr()->print(OS, &MAI);
124+
MC.getExpr()->print(O, &MAI);
119125
else
120126
llvm_unreachable("Invalid operand");
121127
;
122128
}
123129

124-
void XtensaInstPrinter::printCallOperand(const MCInst *MI, int OpNum,
125-
raw_ostream &OS) {
130+
void XtensaInstPrinter::printCallOperand(const MCInst *MI, uint64_t Address,
131+
int OpNum, raw_ostream &O) {
126132
const MCOperand &MC = MI->getOperand(OpNum);
127133
if (MC.isImm()) {
128134
int64_t Val = MC.getImm() + 4;
129-
OS << ". ";
130-
if (Val > 0)
131-
OS << '+';
132-
OS << Val;
135+
if (PrintBranchImmAsAddress) {
136+
uint64_t Target = Address;
137+
Target &= ~0x3;
138+
Target += Val & (~0x3);
139+
O << formatHex(Target);
140+
} else {
141+
O << ". ";
142+
if (Val > 0)
143+
O << '+';
144+
O << Val;
145+
}
133146
} else if (MC.isExpr())
134-
MC.getExpr()->print(OS, &MAI);
147+
MC.getExpr()->print(O, &MAI);
135148
else
136149
llvm_unreachable("Invalid operand");
137150
}
138151

139-
void XtensaInstPrinter::printL32RTarget(const MCInst *MI, int OpNum,
140-
raw_ostream &O) {
152+
void XtensaInstPrinter::printL32RTarget(const MCInst *MI, uint64_t Address,
153+
int OpNum, raw_ostream &O) {
141154
const MCOperand &MC = MI->getOperand(OpNum);
142155
if (MC.isImm()) {
143156
int64_t Value = MI->getOperand(OpNum).getImm();
144-
int64_t InstrOff = Value & 0x3;
145-
Value -= InstrOff;
146-
assert((Value >= -262144 && Value <= -4) &&
147-
"Invalid argument, value must be in ranges [-262144,-4]");
148-
Value += ((InstrOff + 0x3) & 0x4) - InstrOff;
149-
O << ". ";
150-
O << Value;
157+
if (PrintBranchImmAsAddress) {
158+
uint64_t Target = (Address + 0x3) & (~0x3);
159+
Value &= ~0x3;
160+
Target += Value;
161+
O << formatHex(Target);
162+
} else {
163+
int64_t InstrOff = Value & 0x3;
164+
Value -= InstrOff;
165+
assert((Value >= -262144 && Value <= -4) &&
166+
"Invalid argument, value must be in ranges [-262144,-4]");
167+
Value += ((InstrOff + 0x3) & 0x4) - InstrOff;
168+
printPCRelImm(Address, Value, O);
169+
}
151170
} else if (MC.isExpr())
152171
MC.getExpr()->print(O, &MAI);
153172
else
154173
llvm_unreachable("Invalid operand");
155174
}
156175

176+
void XtensaInstPrinter::printPCRelImm(uint64_t Address, int64_t Offset,
177+
raw_ostream &O) {
178+
if (PrintBranchImmAsAddress) {
179+
uint64_t Target = Address + Offset;
180+
Target &= 0xffffffff;
181+
O << formatHex(Target);
182+
} else {
183+
O << ". ";
184+
if (Offset > 0)
185+
O << '+';
186+
O << Offset;
187+
}
188+
}
189+
157190
void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum,
158191
raw_ostream &O) {
159192
if (MI->getOperand(OpNum).isImm()) {
@@ -404,3 +437,14 @@ void XtensaInstPrinter::printB4constu_AsmOperand(const MCInst *MI, int OpNum,
404437
} else
405438
printOperand(MI, OpNum, O);
406439
}
440+
441+
void XtensaInstPrinter::printImm7_22_AsmOperand(const MCInst *MI, int OpNum,
442+
raw_ostream &O) {
443+
if (MI->getOperand(OpNum).isImm()) {
444+
int64_t Value = MI->getOperand(OpNum).getImm();
445+
assert((Value >= 7 && Value <= 22) &&
446+
"Invalid argument, value must be in range <7,22>");
447+
O << Value;
448+
} else
449+
printOperand(MI, OpNum, O);
450+
}

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,17 @@ class XtensaInstPrinter : public MCInstPrinter {
4545
// Print various types of operand.
4646
void printOperand(const MCInst *MI, int OpNum, raw_ostream &O);
4747
void printMemOperand(const MCInst *MI, int OpNUm, raw_ostream &O);
48-
void printBranchTarget(const MCInst *MI, int OpNum, raw_ostream &O);
49-
void printJumpTarget(const MCInst *MI, int OpNum, raw_ostream &O);
50-
void printCallOperand(const MCInst *MI, int OpNum, raw_ostream &O);
51-
void printL32RTarget(const MCInst *MI, int OpNum, raw_ostream &O);
48+
void printBranchTarget(const MCInst *MI, uint64_t Address, int OpNum,
49+
raw_ostream &O);
50+
void printLoopTarget(const MCInst *MI, uint64_t Address, int OpNum,
51+
raw_ostream &O);
52+
void printJumpTarget(const MCInst *MI, uint64_t Address, int OpNum,
53+
raw_ostream &O);
54+
void printCallOperand(const MCInst *MI, uint64_t Address, int OpNum,
55+
raw_ostream &O);
56+
void printL32RTarget(const MCInst *MI, uint64_t Address, int OpNum,
57+
raw_ostream &O);
58+
void printPCRelImm(uint64_t Address, int64_t Offset, raw_ostream &O);
5259

5360
void printImm8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
5461
void printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
@@ -69,6 +76,7 @@ class XtensaInstPrinter : public MCInstPrinter {
6976
void printEntry_Imm12_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
7077
void printB4const_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
7178
void printB4constu_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
79+
void printImm7_22_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
7280
};
7381
} // end namespace llvm
7482

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
6767
SmallVectorImpl<MCFixup> &Fixups,
6868
const MCSubtargetInfo &STI) const;
6969

70+
uint32_t getLoopTargetEncoding(const MCInst &MI, unsigned int OpNum,
71+
SmallVectorImpl<MCFixup> &Fixups,
72+
const MCSubtargetInfo &STI) const;
73+
7074
uint32_t getCallEncoding(const MCInst &MI, unsigned int OpNum,
7175
SmallVectorImpl<MCFixup> &Fixups,
7276
const MCSubtargetInfo &STI) const;
@@ -134,6 +138,10 @@ class XtensaMCCodeEmitter : public MCCodeEmitter {
134138
uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo,
135139
SmallVectorImpl<MCFixup> &Fixups,
136140
const MCSubtargetInfo &STI) const;
141+
142+
uint32_t getImm7_22OpValue(const MCInst &MI, unsigned OpNo,
143+
SmallVectorImpl<MCFixup> &Fixups,
144+
const MCSubtargetInfo &STI) const;
137145
};
138146
} // namespace
139147

@@ -220,6 +228,23 @@ uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
220228
}
221229
}
222230

231+
uint32_t
232+
XtensaMCCodeEmitter::getLoopTargetEncoding(const MCInst &MI, unsigned int OpNum,
233+
SmallVectorImpl<MCFixup> &Fixups,
234+
const MCSubtargetInfo &STI) const {
235+
const MCOperand &MO = MI.getOperand(OpNum);
236+
if (MO.isImm())
237+
return static_cast<uint32_t>(MO.getImm());
238+
239+
assert((MO.isExpr()) && "Unexpected operand value!");
240+
241+
const MCExpr *Expr = MO.getExpr();
242+
243+
Fixups.push_back(MCFixup::create(
244+
0, Expr, MCFixupKind(Xtensa::fixup_xtensa_loop_8), MI.getLoc()));
245+
return 0;
246+
}
247+
223248
uint32_t
224249
XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
225250
SmallVectorImpl<MCFixup> &Fixups,
@@ -554,4 +579,17 @@ XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
554579

555580
return Res;
556581
}
582+
583+
uint32_t
584+
XtensaMCCodeEmitter::getImm7_22OpValue(const MCInst &MI, unsigned OpNo,
585+
SmallVectorImpl<MCFixup> &Fixups,
586+
const MCSubtargetInfo &STI) const {
587+
const MCOperand &MO = MI.getOperand(OpNo);
588+
uint32_t res = static_cast<uint32_t>(MO.getImm());
589+
590+
res -= 7;
591+
assert(((res & 0xf) == res) && "Unexpected operand value!");
592+
593+
return res;
594+
}
557595
#include "XtensaGenMCCodeEmitter.inc"

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits) {
7979
switch (RegNo) {
8080
case Xtensa::BREG:
8181
return FeatureBits[Xtensa::FeatureBoolean];
82+
case Xtensa::LBEG:
83+
case Xtensa::LEND:
84+
case Xtensa::LCOUNT:
85+
return FeatureBits[Xtensa::FeatureLoop];
8286
case Xtensa::WINDOWBASE:
8387
case Xtensa::WINDOWSTART:
8488
return FeatureBits[Xtensa::FeatureWindowed];

llvm/lib/Target/Xtensa/XtensaFeatures.td

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,28 @@ def FeatureBoolean : SubtargetFeature<"bool", "HasBoolean", "true",
2222
"Enable Xtensa Boolean extension">;
2323
def HasBoolean : Predicate<"Subtarget->hasBoolean()">,
2424
AssemblerPredicate<(all_of FeatureBoolean)>;
25+
26+
def FeatureLoop : SubtargetFeature<"loop", "HasLoop", "true",
27+
"Enable Xtensa Loop extension">;
28+
def HasLoop : Predicate<"Subtarget->hasLoop()">,
29+
AssemblerPredicate<(all_of FeatureLoop)>;
30+
31+
def FeatureSEXT : SubtargetFeature<"sext", "HasSEXT", "true",
32+
"Enable Xtensa Sign Extend option">;
33+
def HasSEXT : Predicate<"Subtarget->hasSEXT()">,
34+
AssemblerPredicate<(all_of FeatureSEXT)>;
35+
36+
def FeatureCLAMPS : SubtargetFeature<"clamps", "HasCLAMPS", "true",
37+
"Enable Xtensa CLAMPS option">;
38+
def HasCLAMPS : Predicate<"Subtarget->hasCLAMPS()">,
39+
AssemblerPredicate<(all_of FeatureCLAMPS)>;
40+
41+
def FeatureNSA : SubtargetFeature<"nsa", "HasNSA", "true",
42+
"Enable Xtensa NSA option">;
43+
def HasNSA : Predicate<"Subtarget->hasNSA()">,
44+
AssemblerPredicate<(all_of FeatureNSA)>;
45+
46+
def FeatureMINMAX : SubtargetFeature<"minmax", "HasMINMAX", "true",
47+
"Enable Xtensa MINMAX option">;
48+
def HasMINMAX : Predicate<"Subtarget->hasMINMAX()">,
49+
AssemblerPredicate<(all_of FeatureMINMAX)>;

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
7575
setBooleanContents(ZeroOrOneBooleanContent);
7676

7777
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
78-
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
79-
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
78+
setOperationAction(ISD::SIGN_EXTEND_INREG, {MVT::i8, MVT::i16},
79+
Subtarget.hasSEXT() ? Legal : Expand);
8080

8181
setOperationAction(ISD::BITCAST, MVT::i32, Expand);
8282
setOperationAction(ISD::BITCAST, MVT::f32, Expand);
@@ -141,6 +141,9 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
141141
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
142142
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
143143

144+
setOperationAction({ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX}, MVT::i32,
145+
Subtarget.hasMINMAX() ? Legal : Expand);
146+
144147
// Implement custom stack allocations
145148
setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom);
146149
// Implement custom stack save and restore

0 commit comments

Comments
 (0)