Skip to content

Commit ff25800

Browse files
andreisfrsstefan1
authored andcommitted
[Xtensa 10/10] Add relaxations and fixups. Add rest part of Xtensa Core Instructions
Add branch/jump/call/l32r instructions and fixups support. Add R_XTENSA_32/R_XTENSA_SLOT0_OP relocations in object files generation. Modify tests to support new instructions. Add tests for relocations and fixups. Differential Revision: https://reviews.llvm.org/D64836
1 parent 71199af commit ff25800

19 files changed

+1512
-4
lines changed

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

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/MC/MCContext.h"
1616
#include "llvm/MC/MCExpr.h"
1717
#include "llvm/MC/MCInst.h"
18+
#include "llvm/MC/MCInstrInfo.h"
1819
#include "llvm/MC/MCParser/MCAsmLexer.h"
1920
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
2021
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
@@ -63,6 +64,7 @@ class XtensaAsmParser : public MCTargetAsmParser {
6364
SMLoc &EndLoc) override {
6465
return MatchOperand_NoMatch;
6566
}
67+
OperandMatchResultTy parsePCRelTarget(OperandVector &Operands);
6668

6769
public:
6870
enum XtensaMatchResultTy {
@@ -180,6 +182,66 @@ struct XtensaOperand : public MCParsedAsmOperand {
180182

181183
bool isImm1_16() const { return isImm(1, 16); }
182184

185+
bool isB4const() const {
186+
if (Kind != Immediate)
187+
return false;
188+
if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
189+
int64_t Value = CE->getValue();
190+
switch (Value) {
191+
case -1:
192+
case 1:
193+
case 2:
194+
case 3:
195+
case 4:
196+
case 5:
197+
case 6:
198+
case 7:
199+
case 8:
200+
case 10:
201+
case 12:
202+
case 16:
203+
case 32:
204+
case 64:
205+
case 128:
206+
case 256:
207+
return true;
208+
default:
209+
return false;
210+
}
211+
}
212+
return false;
213+
}
214+
215+
bool isB4constu() const {
216+
if (Kind != Immediate)
217+
return false;
218+
if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
219+
int64_t Value = CE->getValue();
220+
switch (Value) {
221+
case 32768:
222+
case 65536:
223+
case 2:
224+
case 3:
225+
case 4:
226+
case 5:
227+
case 6:
228+
case 7:
229+
case 8:
230+
case 10:
231+
case 12:
232+
case 16:
233+
case 32:
234+
case 64:
235+
case 128:
236+
case 256:
237+
return true;
238+
default:
239+
return false;
240+
}
241+
}
242+
return false;
243+
}
244+
183245
/// getStartLoc - Gets location of the first token of this operand
184246
SMLoc getStartLoc() const override { return StartLoc; }
185247
/// getEndLoc - Gets location of the last token of this operand
@@ -328,6 +390,12 @@ bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
328390
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
329391
"expected immediate in range [-32768, 32512], first 8 bits "
330392
"should be zero");
393+
case Match_InvalidB4const:
394+
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
395+
"expected b4const immediate");
396+
case Match_InvalidB4constu:
397+
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
398+
"expected b4constu immediate");
331399
case Match_InvalidImm12:
332400
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
333401
"expected immediate in range [-2048, 2047]");
@@ -366,6 +434,30 @@ bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
366434
report_fatal_error("Unknown match type detected!");
367435
}
368436

437+
OperandMatchResultTy
438+
XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {
439+
MCAsmParser &Parser = getParser();
440+
LLVM_DEBUG(dbgs() << "parsePCRelTarget\n");
441+
442+
SMLoc S = getLexer().getLoc();
443+
444+
// Expressions are acceptable
445+
const MCExpr *Expr = nullptr;
446+
if (Parser.parseExpression(Expr)) {
447+
// We have no way of knowing if a symbol was consumed so we must ParseFail
448+
return MatchOperand_ParseFail;
449+
}
450+
451+
// Currently not support constants
452+
if (Expr->getKind() == MCExpr::ExprKind::Constant) {
453+
Error(getLoc(), "unknown operand");
454+
return MatchOperand_ParseFail;
455+
}
456+
457+
Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc()));
458+
return MatchOperand_Success;
459+
}
460+
369461
bool XtensaAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
370462
SMLoc &EndLoc) {
371463
const AsmToken &Tok = getParser().getTok();
@@ -486,6 +578,18 @@ XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
486578
/// If operand was parsed, returns false, else true.
487579
bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
488580
bool SR) {
581+
// Check if the current operand has a custom associated parser, if so, try to
582+
// custom parse the operand, or fallback to the general approach.
583+
OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
584+
if (ResTy == MatchOperand_Success)
585+
return false;
586+
587+
// If there wasn't a custom match, try the generic matcher below. Otherwise,
588+
// there was a match, but an error occurred, in which case, just return that
589+
// the operand parsing failed.
590+
if (ResTy == MatchOperand_ParseFail)
591+
return true;
592+
489593
// Attempt to parse token as register
490594
if (parseRegister(Operands, true, SR) == MatchOperand_Success)
491595
return false;

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,59 @@ static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
9494
return MCDisassembler::Fail;
9595
}
9696

97+
static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
98+
uint64_t Address, uint64_t Offset,
99+
uint64_t InstSize, MCInst &MI,
100+
const void *Decoder) {
101+
const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
102+
return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, /*OpSize=*/0,
103+
InstSize);
104+
}
105+
106+
static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm,
107+
int64_t Address, const void *Decoder) {
108+
assert(isUInt<18>(Imm) && "Invalid immediate");
109+
Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2)));
110+
return MCDisassembler::Success;
111+
}
112+
113+
static DecodeStatus decodeJumpOperand(MCInst &Inst, uint64_t Imm,
114+
int64_t Address, const void *Decoder) {
115+
assert(isUInt<18>(Imm) && "Invalid immediate");
116+
Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));
117+
return MCDisassembler::Success;
118+
}
119+
120+
static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm,
121+
int64_t Address, const void *Decoder) {
122+
switch (Inst.getOpcode()) {
123+
case Xtensa::BEQZ:
124+
case Xtensa::BGEZ:
125+
case Xtensa::BLTZ:
126+
case Xtensa::BNEZ:
127+
assert(isUInt<12>(Imm) && "Invalid immediate");
128+
if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true,
129+
Address, 0, 3, Inst, Decoder))
130+
Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
131+
break;
132+
default:
133+
assert(isUInt<8>(Imm) && "Invalid immediate");
134+
if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true,
135+
Address, 0, 3, Inst, Decoder))
136+
Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
137+
}
138+
return MCDisassembler::Success;
139+
}
140+
141+
static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm,
142+
int64_t Address, const void *Decoder) {
143+
144+
assert(isUInt<16>(Imm) && "Invalid immediate");
145+
Inst.addOperand(MCOperand::createImm(
146+
SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));
147+
return MCDisassembler::Success;
148+
}
149+
97150
static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm,
98151
int64_t Address, const void *Decoder) {
99152
assert(isUInt<8>(Imm) && "Invalid immediate");
@@ -145,6 +198,27 @@ static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
145198
return MCDisassembler::Success;
146199
}
147200

201+
static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7,
202+
8, 10, 12, 16, 32, 64, 128, 256};
203+
static DecodeStatus decodeB4constOperand(MCInst &Inst, uint64_t Imm,
204+
int64_t Address, const void *Decoder) {
205+
assert(isUInt<4>(Imm) && "Invalid immediate");
206+
207+
Inst.addOperand(MCOperand::createImm(TableB4const[Imm]));
208+
return MCDisassembler::Success;
209+
}
210+
211+
static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7,
212+
8, 10, 12, 16, 32, 64, 128, 256};
213+
static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm,
214+
int64_t Address,
215+
const void *Decoder) {
216+
assert(isUInt<4>(Imm) && "Invalid immediate");
217+
218+
Inst.addOperand(MCOperand::createImm(TableB4constu[Imm]));
219+
return MCDisassembler::Success;
220+
}
221+
148222
static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm,
149223
int64_t Address, const void *Decoder) {
150224
assert(isUInt<12>(Imm) && "Invalid immediate");

llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ add_llvm_component_library(LLVMXtensaDesc
44
XtensaInstPrinter.cpp
55
XtensaMCAsmInfo.cpp
66
XtensaMCCodeEmitter.cpp
7+
XtensaMCExpr.cpp
78
XtensaMCTargetDesc.cpp
89

910
LINK_COMPONENTS

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

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//
99
//===----------------------------------------------------------------------===//
1010

11+
#include "MCTargetDesc/XtensaFixupKinds.h"
1112
#include "MCTargetDesc/XtensaMCTargetDesc.h"
1213
#include "llvm/MC/MCAsmBackend.h"
1314
#include "llvm/MC/MCAssembler.h"
@@ -31,7 +32,9 @@ class XtensaMCAsmBackend : public MCAsmBackend {
3132
XtensaMCAsmBackend(uint8_t osABI, bool isLE)
3233
: MCAsmBackend(support::little), OSABI(osABI), IsLittleEndian(isLE) {}
3334

34-
unsigned getNumFixupKinds() const override { return 1; }
35+
unsigned getNumFixupKinds() const override {
36+
return Xtensa::NumTargetFixupKinds;
37+
}
3538
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
3639
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
3740
const MCValue &Target, MutableArrayRef<char> Data,
@@ -55,13 +58,113 @@ class XtensaMCAsmBackend : public MCAsmBackend {
5558

5659
const MCFixupKindInfo &
5760
XtensaMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
58-
return MCAsmBackend::getFixupKindInfo(MCFixupKind::FK_NONE);
61+
const static MCFixupKindInfo Infos[Xtensa::NumTargetFixupKinds] = {
62+
// name offset bits flags
63+
{"fixup_xtensa_branch_6", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
64+
{"fixup_xtensa_branch_8", 16, 8, MCFixupKindInfo::FKF_IsPCRel},
65+
{"fixup_xtensa_branch_12", 12, 12, MCFixupKindInfo::FKF_IsPCRel},
66+
{"fixup_xtensa_jump_18", 6, 18, MCFixupKindInfo::FKF_IsPCRel},
67+
{"fixup_xtensa_call_18", 6, 18,
68+
MCFixupKindInfo::FKF_IsPCRel |
69+
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
70+
{"fixup_xtensa_l32r_16", 8, 16,
71+
MCFixupKindInfo::FKF_IsPCRel |
72+
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}};
73+
74+
if (Kind < FirstTargetFixupKind)
75+
return MCAsmBackend::getFixupKindInfo(Kind);
76+
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
77+
"Invalid kind!");
78+
return Infos[Kind - FirstTargetFixupKind];
79+
}
80+
81+
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
82+
MCContext &Ctx) {
83+
unsigned Kind = Fixup.getKind();
84+
switch (Kind) {
85+
default:
86+
llvm_unreachable("Unknown fixup kind!");
87+
case FK_Data_1:
88+
case FK_Data_2:
89+
case FK_Data_4:
90+
case FK_Data_8:
91+
return Value;
92+
case Xtensa::fixup_xtensa_branch_6: {
93+
Value -= 4;
94+
if (!isInt<6>(Value))
95+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
96+
unsigned Hi2 = (Value >> 4) & 0x3;
97+
unsigned Lo4 = Value & 0xf;
98+
return (Hi2 << 4) | (Lo4 << 12);
99+
}
100+
case Xtensa::fixup_xtensa_branch_8:
101+
Value -= 4;
102+
if (!isInt<8>(Value))
103+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
104+
return (Value & 0xff);
105+
case Xtensa::fixup_xtensa_branch_12:
106+
Value -= 4;
107+
if (!isInt<12>(Value))
108+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
109+
return (Value & 0xfff);
110+
case Xtensa::fixup_xtensa_jump_18:
111+
Value -= 4;
112+
if (!isInt<18>(Value))
113+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
114+
return (Value & 0x3ffff);
115+
case Xtensa::fixup_xtensa_call_18:
116+
Value -= 4;
117+
if (!isInt<20>(Value))
118+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
119+
if (Value & 0x3)
120+
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
121+
return (Value & 0xffffc) >> 2;
122+
case Xtensa::fixup_xtensa_l32r_16:
123+
unsigned Offset = Fixup.getOffset();
124+
if (Offset & 0x3)
125+
Value -= 4;
126+
if (!isInt<18>(Value) && (Value & 0x20000))
127+
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
128+
if (Value & 0x3)
129+
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
130+
return (Value & 0x3fffc) >> 2;
131+
}
59132
}
133+
134+
static unsigned getSize(unsigned Kind) {
135+
switch (Kind) {
136+
default:
137+
return 3;
138+
case MCFixupKind::FK_Data_4:
139+
return 4;
140+
case Xtensa::fixup_xtensa_branch_6:
141+
return 2;
142+
}
143+
}
144+
60145
void XtensaMCAsmBackend::applyFixup(const MCAssembler &Asm,
61146
const MCFixup &Fixup, const MCValue &Target,
62147
MutableArrayRef<char> Data, uint64_t Value,
63148
bool IsResolved,
64-
const MCSubtargetInfo *STI) const {}
149+
const MCSubtargetInfo *STI) const {
150+
MCContext &Ctx = Asm.getContext();
151+
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
152+
153+
Value = adjustFixupValue(Fixup, Value, Ctx);
154+
155+
// Shift the value into position.
156+
Value <<= Info.TargetOffset;
157+
158+
if (!Value)
159+
return; // Doesn't change encoding.
160+
161+
unsigned Offset = Fixup.getOffset();
162+
unsigned FullSize = getSize(Fixup.getKind());
163+
164+
for (unsigned i = 0; i != FullSize; ++i) {
165+
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
166+
}
167+
}
65168

66169
bool XtensaMCAsmBackend::mayNeedRelaxation(const MCInst &Inst,
67170
const MCSubtargetInfo &STI) const {

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ XtensaObjectWriter::~XtensaObjectWriter() {}
4646
unsigned XtensaObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
4747
const MCFixup &Fixup,
4848
bool IsPCRel) const {
49-
report_fatal_error("invalid fixup kind!");
49+
50+
switch ((unsigned)Fixup.getKind()) {
51+
case FK_Data_4:
52+
return ELF::R_XTENSA_32;
53+
default:
54+
return ELF::R_XTENSA_SLOT0_OP;
55+
}
5056
}
5157

5258
std::unique_ptr<MCObjectTargetWriter>

0 commit comments

Comments
 (0)