mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[CSKY 6/n] Add support branch and symbol series instruction
This patch adds basic CSKY branch instructions and symbol address series instructions. Those two kinds of instruction have relationship between each other, and it involves much work about Fixups. For now, basic instructions are enabled except for disassembler support. We would support to generate basic codegen asm firstly and delay disassembler work later. Differential Revision: https://reviews.llvm.org/D95029
This commit is contained in:
parent
2b6d3d4a3f
commit
ca9ceef593
@ -7,6 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/CSKYMCExpr.h"
|
||||
#include "MCTargetDesc/CSKYMCTargetDesc.h"
|
||||
#include "TargetInfo/CSKYTargetInfo.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@ -58,6 +59,8 @@ class CSKYAsmParser : public MCTargetAsmParser {
|
||||
OperandMatchResultTy parseImmediate(OperandVector &Operands);
|
||||
OperandMatchResultTy parseRegister(OperandVector &Operands);
|
||||
OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
|
||||
OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands);
|
||||
OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands);
|
||||
|
||||
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
|
||||
|
||||
@ -171,6 +174,20 @@ public:
|
||||
bool isUImm12Shift1() { return isUImm<12, 1>(); }
|
||||
bool isUImm12Shift2() { return isUImm<12, 2>(); }
|
||||
|
||||
bool isSImm16Shift1() { return isSImm<16, 1>(); }
|
||||
|
||||
bool isCSKYSymbol() const {
|
||||
int64_t Imm;
|
||||
// Must be of 'immediate' type but not a constant.
|
||||
return isImm() && !evaluateConstantImm(getImm(), Imm);
|
||||
}
|
||||
|
||||
bool isConstpoolSymbol() const {
|
||||
int64_t Imm;
|
||||
// Must be of 'immediate' type but not a constant.
|
||||
return isImm() && !evaluateConstantImm(getImm(), Imm);
|
||||
}
|
||||
|
||||
/// Gets location of the first token of this operand.
|
||||
SMLoc getStartLoc() const override { return StartLoc; }
|
||||
/// Gets location of the last token of this operand.
|
||||
@ -350,6 +367,14 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
"immediate must be a multiple of 4 bytes in the range");
|
||||
case Match_InvalidUImm16:
|
||||
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
|
||||
case Match_InvalidCSKYSymbol: {
|
||||
SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
|
||||
return Error(ErrorLoc, "operand must be a symbol name");
|
||||
}
|
||||
case Match_InvalidConstpool: {
|
||||
SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
|
||||
return Error(ErrorLoc, "operand must be a constpool symbol name");
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("Unknown match type detected!");
|
||||
@ -482,6 +507,15 @@ OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
|
||||
/// information, adding to Operands. If operand was parsed, returns false, else
|
||||
/// true.
|
||||
bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
|
||||
// Check if the current operand has a custom associated parser, if so, try to
|
||||
// custom parse the operand, or fallback to the general approach.
|
||||
OperandMatchResultTy Result =
|
||||
MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
|
||||
if (Result == MatchOperand_Success)
|
||||
return false;
|
||||
if (Result == MatchOperand_ParseFail)
|
||||
return true;
|
||||
|
||||
// Attempt to parse token as register
|
||||
if (parseRegister(Operands) == MatchOperand_Success)
|
||||
return false;
|
||||
@ -500,6 +534,68 @@ bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
|
||||
return true;
|
||||
}
|
||||
|
||||
OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
|
||||
SMLoc S = getLoc();
|
||||
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
|
||||
|
||||
if (getLexer().getKind() != AsmToken::Identifier)
|
||||
return MatchOperand_NoMatch;
|
||||
|
||||
StringRef Identifier;
|
||||
if (getParser().parseIdentifier(Identifier))
|
||||
return MatchOperand_ParseFail;
|
||||
|
||||
CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;
|
||||
|
||||
if (Identifier.consume_back("@GOT"))
|
||||
Kind = CSKYMCExpr::VK_CSKY_GOT;
|
||||
else if (Identifier.consume_back("@GOTOFF"))
|
||||
Kind = CSKYMCExpr::VK_CSKY_GOTOFF;
|
||||
else if (Identifier.consume_back("@PLT"))
|
||||
Kind = CSKYMCExpr::VK_CSKY_PLT;
|
||||
else if (Identifier.consume_back("@GOTPC"))
|
||||
Kind = CSKYMCExpr::VK_CSKY_GOTPC;
|
||||
|
||||
MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
|
||||
const MCExpr *Res =
|
||||
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
|
||||
|
||||
if (Kind != CSKYMCExpr::VK_CSKY_None)
|
||||
Res = CSKYMCExpr::create(Res, Kind, getContext());
|
||||
|
||||
Operands.push_back(CSKYOperand::createImm(Res, S, E));
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
OperandMatchResultTy
|
||||
CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
|
||||
SMLoc S = getLoc();
|
||||
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
|
||||
|
||||
if (getLexer().getKind() != AsmToken::LBrac)
|
||||
return MatchOperand_NoMatch;
|
||||
|
||||
getLexer().Lex(); // Eat '['.
|
||||
|
||||
if (getLexer().getKind() != AsmToken::Identifier)
|
||||
return MatchOperand_NoMatch;
|
||||
|
||||
StringRef Identifier;
|
||||
if (getParser().parseIdentifier(Identifier))
|
||||
return MatchOperand_ParseFail;
|
||||
|
||||
if (getLexer().getKind() != AsmToken::RBrac)
|
||||
return MatchOperand_NoMatch;
|
||||
|
||||
getLexer().Lex(); // Eat ']'.
|
||||
|
||||
MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
|
||||
const MCExpr *Res =
|
||||
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
|
||||
Operands.push_back(CSKYOperand::createImm(Res, S, E));
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||
SMLoc NameLoc, OperandVector &Operands) {
|
||||
// First operand is token for instruction.
|
||||
|
@ -54,13 +54,14 @@ class J<bits<6> opcode, dag outs, dag ins, string op, list<dag> pattern>
|
||||
pattern> {
|
||||
bits<26> offset;
|
||||
let Inst{25 - 0} = offset;
|
||||
let isCall = 1;
|
||||
let Defs = [ R15 ];
|
||||
}
|
||||
|
||||
// Format< OP[6] | RZ[5] | SOP[3] | OFFSET[18] >
|
||||
// Instructions(7): grs, lrs32.b, lrs32.h, lrs32.w, srs32.b, srs32.h, srs32.w
|
||||
class I_18_Z_L<bits<3> sop, string op, dag outs, dag ins, list<dag> pattern>
|
||||
: CSKY32Inst<AddrModeNone, 0x33, outs, ins,
|
||||
!strconcat(op, "\t$rz, $offset"), pattern> {
|
||||
class I_18_Z_L<bits<3> sop, string asm, dag outs, dag ins, list<dag> pattern>
|
||||
: CSKY32Inst<AddrModeNone, 0x33, outs, ins, asm, pattern> {
|
||||
bits<5> rz;
|
||||
bits<18> offset;
|
||||
let Inst{25 - 21} = rz;
|
||||
@ -102,7 +103,7 @@ class I_16_MOV<bits<5> sop, string op, ImmLeaf ImmType>
|
||||
// Instructions(1): lrw32
|
||||
class I_16_Z_L<bits<5> sop, string op, dag ins, list<dag> pattern>
|
||||
: CSKY32Inst<AddrModeNone, 0x3a, (outs GPR:$rz), ins,
|
||||
!strconcat(op, "\t$rz, [$imm16]"), pattern> {
|
||||
!strconcat(op, "\t$rz, $imm16"), pattern> {
|
||||
bits<5> rz;
|
||||
bits<16> imm16;
|
||||
let Inst{25 - 21} = sop;
|
||||
@ -112,9 +113,8 @@ class I_16_Z_L<bits<5> sop, string op, dag ins, list<dag> pattern>
|
||||
|
||||
// Format< OP[6] | SOP[5] | 00000[5] | OFFSET[16] >
|
||||
// Instructions(5): bt32, bf32, br32, jmpi32, jsri32
|
||||
class I_16_L<bits<5> sop, dag outs, dag ins, string op, list<dag> pattern>
|
||||
: CSKY32Inst<AddrModeNone, 0x3a, outs, ins, !strconcat(op, "\t$imm16"),
|
||||
pattern> {
|
||||
class I_16_L<bits<5> sop, dag outs, dag ins, string asm, list<dag> pattern>
|
||||
: CSKY32Inst<AddrModeNone, 0x3a, outs, ins, asm, pattern> {
|
||||
bits<16> imm16;
|
||||
let Inst{25 - 21} = sop;
|
||||
let Inst{20 - 16} = 0;
|
||||
@ -159,6 +159,19 @@ class I_16_RET<bits<5> sop, bits<5> pcode, string op, list<dag> pattern>
|
||||
let isBarrier = 1;
|
||||
}
|
||||
|
||||
// Instructions(1): rte32
|
||||
class I_16_RET_I<bits<5> sop, bits<5> pcode, string op, list<dag> pattern>
|
||||
: CSKY32Inst<AddrModeNone, 0x30, (outs), (ins), op, pattern> {
|
||||
let Inst{25 - 21} = sop;
|
||||
let Inst{20 - 16} = pcode;
|
||||
let Inst{15 - 10} = 0x10;
|
||||
let Inst{9 - 5} = 1;
|
||||
let Inst{4 - 0} = 0;
|
||||
let isTerminator = 1;
|
||||
let isReturn = 1;
|
||||
let isBarrier = 1;
|
||||
}
|
||||
|
||||
// Format< OP[6] | SOP[5] | RX[5] | IMM16[16] >
|
||||
// Instructions(3): cmpnei32, cmphsi32, cmplti32
|
||||
class I_16_X<bits<5> sop, string op, Operand operand>
|
||||
|
@ -15,7 +15,9 @@
|
||||
// CSKY specific DAG Nodes.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// TODO: Add CSKY specific DAG Nodes.
|
||||
// Target-dependent nodes.
|
||||
def CSKY_RET : SDNode<"CSKYISD::RET", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Operand and SDNode transformation definitions.
|
||||
@ -81,6 +83,41 @@ def uimm_shift : Operand<i32>, ImmLeaf<i32, "return isUInt<2>(Imm);"> {
|
||||
let ParserMatchClass = UImmAsmOperand<2>;
|
||||
}
|
||||
|
||||
def CSKYSymbol : AsmOperandClass {
|
||||
let Name = "CSKYSymbol";
|
||||
let RenderMethod = "addImmOperands";
|
||||
let DiagnosticType = "InvalidCSKYSymbol";
|
||||
let ParserMethod = "parseCSKYSymbol";
|
||||
}
|
||||
|
||||
def br_symbol : Operand<iPTR> {
|
||||
let EncoderMethod =
|
||||
"getBranchSymbolOpValue<CSKY::fixup_csky_pcrel_imm16_scale2>";
|
||||
let ParserMatchClass = CSKYSymbol;
|
||||
}
|
||||
|
||||
def call_symbol : Operand<iPTR> {
|
||||
let ParserMatchClass = CSKYSymbol;
|
||||
let EncoderMethod = "getCallSymbolOpValue";
|
||||
}
|
||||
|
||||
def Constpool : AsmOperandClass {
|
||||
let Name = "ConstpoolSymbol";
|
||||
let RenderMethod = "addImmOperands";
|
||||
let DiagnosticType = "InvalidConstpool";
|
||||
let ParserMethod = "parseConstpoolSymbol";
|
||||
}
|
||||
|
||||
def constpool_symbol : Operand<iPTR> {
|
||||
let ParserMatchClass = Constpool;
|
||||
let EncoderMethod =
|
||||
"getConstpoolSymbolOpValue<CSKY::fixup_csky_pcrel_uimm16_scale4>";
|
||||
}
|
||||
|
||||
def bare_symbol : Operand<iPTR> {
|
||||
let ParserMatchClass = CSKYSymbol;
|
||||
let EncoderMethod = "getBareSymbolOpValue";
|
||||
}
|
||||
|
||||
def oimm12 : oimm<12>;
|
||||
def oimm16 : oimm<16>;
|
||||
@ -229,3 +266,69 @@ def MOVIH32 : I_16_MOV<0x11, "movih32", uimm16_16_xform>;
|
||||
|
||||
def MVC32 : R_Z_1<0x1, 0x8, "mvc32">;
|
||||
def MVCV32 : R_Z_1<0x1, 0x10, "mvcv32">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Branch and call instructions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let isBranch = 1, isTerminator = 1 in {
|
||||
let isBarrier = 1, isPredicable = 1 in
|
||||
def BR32 : I_16_L<0x0, (outs), (ins br_symbol:$imm16), "br32\t$imm16",
|
||||
[(br bb:$imm16)]>;
|
||||
|
||||
def BT32 : I_16_L<0x3, (outs), (ins CARRY:$ca, br_symbol:$imm16),
|
||||
"bt32\t$imm16", [(brcond CARRY:$ca, bb:$imm16)]>;
|
||||
def BF32 : I_16_L<0x2, (outs), (ins CARRY:$ca, br_symbol:$imm16),
|
||||
"bf32\t$imm16", []>;
|
||||
}
|
||||
|
||||
|
||||
def BEZ32 : I_16_X_L<0x8, "bez32", br_symbol>;
|
||||
def BNEZ32 : I_16_X_L<0x9, "bnez32", br_symbol>;
|
||||
def BHZ32 : I_16_X_L<0xA, "bhz32", br_symbol>;
|
||||
def BLSZ32 : I_16_X_L<0xB, "blsz32", br_symbol>;
|
||||
def BLZ32 : I_16_X_L<0xC, "blz32", br_symbol>;
|
||||
def BHSZ32 : I_16_X_L<0xD, "bhsz32", br_symbol>;
|
||||
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
|
||||
def JMP32 : I_16_JX<0x6, "jmp32", [(brind GPR:$rx)]>; // jmp to register
|
||||
def JMPI32 : I_16_L<0x16, (outs), (ins constpool_symbol:$imm16),
|
||||
"jmpi32\t$imm16", []>;
|
||||
}
|
||||
|
||||
let isCall = 1, Defs = [ R15 ] in
|
||||
def JSR32 : I_16_JX<0x7, "jsr32", []>;
|
||||
|
||||
let isCall = 1, Defs = [ R15 ] , mayLoad = 1 in
|
||||
def JSRI32: I_16_L<0x17, (outs),
|
||||
(ins constpool_symbol:$imm16), "jsri32\t$imm16", []>;
|
||||
|
||||
|
||||
def BSR32 : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>;
|
||||
|
||||
def BSR32_BR : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>{
|
||||
let isCodeGenOnly = 1;
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
let isBarrier = 1;
|
||||
let isPredicable = 1;
|
||||
let Defs = [ R15 ];
|
||||
}
|
||||
|
||||
def RTS32 : I_16_RET<0x6, 0xF, "rts32", [(CSKY_RET)]>;
|
||||
|
||||
|
||||
def RTE32 : I_16_RET_I<0, 0, "rte32", []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Symbol address instructions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def GRS32 : I_18_Z_L<0x3, "grs32\t$rz, $offset",
|
||||
(outs GPR:$rz), (ins bare_symbol:$offset), []>;
|
||||
|
||||
let mayLoad = 1, mayStore = 0 in {
|
||||
def LRW32 : I_16_Z_L<0x14, "lrw32", (ins constpool_symbol:$imm16), []>;
|
||||
let isCodeGenOnly = 1 in
|
||||
def LRW32_Gen : I_16_Z_L<0x14, "lrw32", (ins bare_symbol:$src1, constpool_symbol:$imm16), []>;
|
||||
}
|
@ -3,6 +3,7 @@ add_llvm_component_library(LLVMCSKYDesc
|
||||
CSKYELFObjectWriter.cpp
|
||||
CSKYInstPrinter.cpp
|
||||
CSKYMCAsmInfo.cpp
|
||||
CSKYMCExpr.cpp
|
||||
CSKYMCTargetDesc.cpp
|
||||
CSKYMCCodeEmitter.cpp
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "CSKYAsmBackend.h"
|
||||
#include "MCTargetDesc/CSKYMCTargetDesc.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
@ -24,14 +25,113 @@ CSKYAsmBackend::createObjectTargetWriter() const {
|
||||
return createCSKYELFObjectWriter();
|
||||
}
|
||||
|
||||
unsigned int CSKYAsmBackend::getNumFixupKinds() const { return 1; }
|
||||
const MCFixupKindInfo &
|
||||
CSKYAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
||||
|
||||
static llvm::DenseMap<unsigned, MCFixupKindInfo> Infos = {
|
||||
{CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},
|
||||
{CSKY::Fixups::fixup_csky_pcrel_imm16_scale2,
|
||||
{"fixup_csky_pcrel_imm16_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
|
||||
{CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4,
|
||||
{"fixup_csky_pcrel_uimm16_scale4", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
|
||||
{CSKY::Fixups::fixup_csky_pcrel_imm26_scale2,
|
||||
{"fixup_csky_pcrel_imm26_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
|
||||
{CSKY::Fixups::fixup_csky_pcrel_imm18_scale2,
|
||||
{"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}};
|
||||
assert(Infos.size() == CSKY::NumTargetFixupKinds &&
|
||||
"Not all fixup kinds added to Infos array");
|
||||
|
||||
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
|
||||
"Invalid kind!");
|
||||
if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind)
|
||||
return Infos[Kind];
|
||||
else if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
else
|
||||
return MCAsmBackend::getFixupKindInfo(FK_NONE);
|
||||
}
|
||||
|
||||
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
|
||||
MCContext &Ctx) {
|
||||
switch (Fixup.getTargetKind()) {
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
case FK_Data_1:
|
||||
case FK_Data_2:
|
||||
case FK_Data_4:
|
||||
case FK_Data_8:
|
||||
return Value;
|
||||
case CSKY::fixup_csky_addr32:
|
||||
return Value & 0xffffffff;
|
||||
case CSKY::fixup_csky_pcrel_imm16_scale2:
|
||||
if (!isIntN(17, Value))
|
||||
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
|
||||
if (Value & 0x1)
|
||||
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
|
||||
|
||||
return (Value >> 1) & 0xffff;
|
||||
case CSKY::fixup_csky_pcrel_uimm16_scale4:
|
||||
if (!isUIntN(18, Value))
|
||||
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
|
||||
if (Value & 0x3)
|
||||
Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
|
||||
|
||||
return (Value >> 2) & 0xffff;
|
||||
case CSKY::fixup_csky_pcrel_imm26_scale2:
|
||||
if (!isIntN(27, Value))
|
||||
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
|
||||
if (Value & 0x1)
|
||||
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
|
||||
|
||||
return (Value >> 1) & 0x3ffffff;
|
||||
case CSKY::fixup_csky_pcrel_imm18_scale2:
|
||||
if (!isIntN(19, Value))
|
||||
Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
|
||||
if (Value & 0x1)
|
||||
Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
|
||||
|
||||
return (Value >> 1) & 0x3ffff;
|
||||
}
|
||||
}
|
||||
|
||||
void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target,
|
||||
MutableArrayRef<char> Data, uint64_t Value,
|
||||
bool IsResolved,
|
||||
const MCSubtargetInfo *STI) const {
|
||||
return;
|
||||
MCFixupKind Kind = Fixup.getKind();
|
||||
if (Kind >= FirstLiteralRelocationKind)
|
||||
return;
|
||||
MCContext &Ctx = Asm.getContext();
|
||||
MCFixupKindInfo Info = getFixupKindInfo(Kind);
|
||||
if (!Value)
|
||||
return; // Doesn't change encoding.
|
||||
// Apply any target-specific value adjustments.
|
||||
Value = adjustFixupValue(Fixup, Value, Ctx);
|
||||
|
||||
// Shift the value into position.
|
||||
Value <<= Info.TargetOffset;
|
||||
|
||||
unsigned Offset = Fixup.getOffset();
|
||||
unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
|
||||
|
||||
assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
|
||||
|
||||
// For each byte of the fragment that the fixup touches, mask in the
|
||||
// bits from the fixup value.
|
||||
bool IsLittleEndian = (Endian == support::little);
|
||||
|
||||
if (IsLittleEndian && (NumBytes == 4)) {
|
||||
Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff);
|
||||
Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff);
|
||||
Data[Offset + 2] |= uint8_t(Value & 0xff);
|
||||
Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff);
|
||||
} else {
|
||||
for (unsigned I = 0; I != NumBytes; I++) {
|
||||
unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);
|
||||
Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYASMBACKEND_H
|
||||
#define LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYASMBACKEND_H
|
||||
|
||||
#include "MCTargetDesc/CSKYFixupKinds.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCTargetOptions.h"
|
||||
|
||||
@ -20,17 +21,26 @@ public:
|
||||
CSKYAsmBackend(const MCSubtargetInfo &STI, const MCTargetOptions &OP)
|
||||
: MCAsmBackend(support::little) {}
|
||||
|
||||
unsigned int getNumFixupKinds() const override;
|
||||
unsigned int getNumFixupKinds() const override {
|
||||
return CSKY::NumTargetFixupKinds;
|
||||
}
|
||||
|
||||
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsResolved,
|
||||
const MCSubtargetInfo *STI) const override;
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
|
||||
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override;
|
||||
|
||||
void relaxInstruction(MCInst &Inst,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
|
||||
bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
|
||||
|
||||
std::unique_ptr<MCObjectTargetWriter>
|
||||
createObjectTargetWriter() const override;
|
||||
};
|
||||
|
34
lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
Normal file
34
lib/Target/CSKY/MCTargetDesc/CSKYFixupKinds.h
Normal file
@ -0,0 +1,34 @@
|
||||
//===-- CSKYFixupKinds.h - CSKY Specific Fixup Entries ----------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYFIXUPKINDS_H
|
||||
#define LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYFIXUPKINDS_H
|
||||
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace CSKY {
|
||||
enum Fixups {
|
||||
fixup_csky_addr32 = FirstTargetFixupKind,
|
||||
|
||||
fixup_csky_pcrel_imm16_scale2,
|
||||
|
||||
fixup_csky_pcrel_uimm16_scale4,
|
||||
|
||||
fixup_csky_pcrel_imm26_scale2,
|
||||
|
||||
fixup_csky_pcrel_imm18_scale2,
|
||||
|
||||
// Marker
|
||||
fixup_csky_invalid,
|
||||
NumTargetFixupKinds = fixup_csky_invalid - FirstTargetFixupKind
|
||||
};
|
||||
} // end namespace CSKY
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYFIXUPKINDS_H
|
@ -62,6 +62,17 @@ CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||||
return 0;
|
||||
}
|
||||
|
||||
MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {
|
||||
const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr);
|
||||
|
||||
switch (CSKYExpr->getKind()) {
|
||||
default:
|
||||
llvm_unreachable("Unhandled fixup kind!");
|
||||
case CSKYMCExpr::VK_CSKY_ADDR:
|
||||
return MCFixupKind(CSKY::fixup_csky_addr32);
|
||||
}
|
||||
}
|
||||
|
||||
MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx) {
|
||||
|
@ -13,6 +13,8 @@
|
||||
#ifndef LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYMCCODEEMITTER_H
|
||||
#define LLVM_LIB_TARGET_CSKY_MCTARGETDESC_CSKYMCCODEEMITTER_H
|
||||
|
||||
#include "CSKYMCExpr.h"
|
||||
#include "MCTargetDesc/CSKYFixupKinds.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
|
||||
@ -62,6 +64,70 @@ public:
|
||||
assert(MO.isImm() && "Unexpected MO type.");
|
||||
return 1 << MO.getImm();
|
||||
}
|
||||
|
||||
MCFixupKind getTargetFixup(const MCExpr *Expr) const;
|
||||
|
||||
template <llvm::CSKY::Fixups FIXUP>
|
||||
unsigned getBranchSymbolOpValue(const MCInst &MI, unsigned Idx,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand &MO = MI.getOperand(Idx);
|
||||
|
||||
if (MO.isImm())
|
||||
return MO.getImm() >> 1;
|
||||
|
||||
assert(MO.isExpr() && "Unexpected MO type.");
|
||||
|
||||
MCFixupKind Kind = MCFixupKind(FIXUP);
|
||||
if (MO.getExpr()->getKind() == MCExpr::Target)
|
||||
Kind = getTargetFixup(MO.getExpr());
|
||||
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <llvm::CSKY::Fixups FIXUP>
|
||||
unsigned getConstpoolSymbolOpValue(const MCInst &MI, unsigned Idx,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand &MO = MI.getOperand(Idx);
|
||||
assert(MO.isExpr() && "Unexpected MO type.");
|
||||
|
||||
MCFixupKind Kind = MCFixupKind(FIXUP);
|
||||
if (MO.getExpr()->getKind() == MCExpr::Target)
|
||||
Kind = getTargetFixup(MO.getExpr());
|
||||
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned getCallSymbolOpValue(const MCInst &MI, unsigned Idx,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand &MO = MI.getOperand(Idx);
|
||||
assert(MO.isExpr() && "Unexpected MO type.");
|
||||
|
||||
MCFixupKind Kind = MCFixupKind(CSKY::fixup_csky_pcrel_imm26_scale2);
|
||||
if (MO.getExpr()->getKind() == MCExpr::Target)
|
||||
Kind = getTargetFixup(MO.getExpr());
|
||||
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned getBareSymbolOpValue(const MCInst &MI, unsigned Idx,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand &MO = MI.getOperand(Idx);
|
||||
assert(MO.isExpr() && "Unexpected MO type.");
|
||||
|
||||
MCFixupKind Kind = MCFixupKind(CSKY::fixup_csky_pcrel_imm18_scale2);
|
||||
if (MO.getExpr()->getKind() == MCExpr::Target)
|
||||
Kind = getTargetFixup(MO.getExpr());
|
||||
|
||||
Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc()));
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
122
lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
Normal file
122
lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
//===-- CSKYMCExpr.cpp - CSKY specific MC expression classes -*- C++ -*----===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CSKYMCExpr.h"
|
||||
#include "CSKYFixupKinds.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "csky-mc-expr"
|
||||
|
||||
const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind,
|
||||
MCContext &Ctx) {
|
||||
return new (Ctx) CSKYMCExpr(Kind, Expr);
|
||||
}
|
||||
|
||||
StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) {
|
||||
switch (Kind) {
|
||||
default:
|
||||
llvm_unreachable("Invalid ELF symbol kind");
|
||||
case VK_CSKY_ADDR:
|
||||
return "";
|
||||
case VK_CSKY_PCREL:
|
||||
return "";
|
||||
case VK_CSKY_GOT:
|
||||
return "@GOT";
|
||||
case VK_CSKY_GOTPC:
|
||||
return "@GOTPC";
|
||||
case VK_CSKY_GOTOFF:
|
||||
return "@GOTOFF";
|
||||
case VK_CSKY_PLT:
|
||||
return "@PLT";
|
||||
case VK_CSKY_TPOFF:
|
||||
return "@TPOFF";
|
||||
case VK_CSKY_TLSGD:
|
||||
return "@TLSGD";
|
||||
}
|
||||
}
|
||||
|
||||
void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
|
||||
Streamer.visitUsedExpr(*getSubExpr());
|
||||
}
|
||||
|
||||
void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
|
||||
Expr->print(OS, MAI);
|
||||
OS << getVariantKindName(getKind());
|
||||
}
|
||||
|
||||
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
|
||||
switch (Expr->getKind()) {
|
||||
case MCExpr::Target:
|
||||
llvm_unreachable("Can't handle nested target expression");
|
||||
break;
|
||||
case MCExpr::Constant:
|
||||
break;
|
||||
|
||||
case MCExpr::Binary: {
|
||||
const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
|
||||
fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
|
||||
fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
|
||||
break;
|
||||
}
|
||||
|
||||
case MCExpr::SymbolRef: {
|
||||
// We're known to be under a TLS fixup, so any symbol should be
|
||||
// modified. There should be only one.
|
||||
const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
|
||||
cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
|
||||
break;
|
||||
}
|
||||
|
||||
case MCExpr::Unary:
|
||||
fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
|
||||
switch (getKind()) {
|
||||
default:
|
||||
return;
|
||||
case VK_CSKY_TPOFF:
|
||||
case VK_CSKY_TLSGD:
|
||||
break;
|
||||
}
|
||||
|
||||
fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
|
||||
}
|
||||
|
||||
bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const {
|
||||
if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
|
||||
return false;
|
||||
|
||||
// Some custom fixup types are not valid with symbol difference expressions
|
||||
if (Res.getSymA() && Res.getSymB()) {
|
||||
switch (getKind()) {
|
||||
default:
|
||||
return true;
|
||||
|
||||
case VK_CSKY_ADDR:
|
||||
case VK_CSKY_PCREL:
|
||||
case VK_CSKY_GOT:
|
||||
case VK_CSKY_GOTPC:
|
||||
case VK_CSKY_GOTOFF:
|
||||
case VK_CSKY_TPOFF:
|
||||
case VK_CSKY_TLSGD:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
69
lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
Normal file
69
lib/Target/CSKY/MCTargetDesc/CSKYMCExpr.h
Normal file
@ -0,0 +1,69 @@
|
||||
//===-- CSKYMCExpr.h - CSKY specific MC expression classes -*- C++ -*----===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCEXPR_H
|
||||
#define LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCEXPR_H
|
||||
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class CSKYMCExpr : public MCTargetExpr {
|
||||
public:
|
||||
enum VariantKind {
|
||||
VK_CSKY_None,
|
||||
VK_CSKY_ADDR,
|
||||
VK_CSKY_PCREL,
|
||||
VK_CSKY_GOT,
|
||||
VK_CSKY_GOTPC,
|
||||
VK_CSKY_GOTOFF,
|
||||
VK_CSKY_PLT,
|
||||
VK_CSKY_TPOFF,
|
||||
VK_CSKY_TLSGD,
|
||||
VK_CSKY_Invalid
|
||||
};
|
||||
|
||||
private:
|
||||
const VariantKind Kind;
|
||||
const MCExpr *Expr;
|
||||
|
||||
explicit CSKYMCExpr(VariantKind Kind, const MCExpr *Expr)
|
||||
: Kind(Kind), Expr(Expr) {}
|
||||
|
||||
public:
|
||||
static const CSKYMCExpr *create(const MCExpr *Expr, VariantKind Kind,
|
||||
MCContext &Ctx);
|
||||
|
||||
// Returns the kind of this expression.
|
||||
VariantKind getKind() const { return Kind; }
|
||||
|
||||
// Returns the child of this expression.
|
||||
const MCExpr *getSubExpr() const { return Expr; }
|
||||
|
||||
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
|
||||
|
||||
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const override;
|
||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||
|
||||
MCFragment *findAssociatedFragment() const override {
|
||||
return getSubExpr()->findAssociatedFragment();
|
||||
}
|
||||
|
||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
|
||||
|
||||
static bool classof(const MCExpr *E) {
|
||||
return E->getKind() == MCExpr::Target;
|
||||
}
|
||||
|
||||
static StringRef getVariantKindName(VariantKind Kind);
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -240,6 +240,102 @@ zext32 a3, l0, 7, 0
|
||||
# CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x58]
|
||||
sext32 a3, l0, 7, 0
|
||||
|
||||
# CHECK-ASM: br32 .L.test
|
||||
# CHECK-ASM: encoding: [A,0xe8'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test:
|
||||
br32 .L.test
|
||||
|
||||
# CHECK-ASM: bt32 .L.test2
|
||||
# CHECK-ASM: encoding: [0x60'A',0xe8'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test2, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test2:
|
||||
bt32 .L.test2
|
||||
|
||||
# CHECK-ASM: bf32 .L.test3
|
||||
# CHECK-ASM: encoding: [0x40'A',0xe8'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test3, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test3:
|
||||
bf32 .L.test3
|
||||
|
||||
# CHECK-ASM: bez32 a0, .L.test4
|
||||
# CHECK-ASM: encoding: [A,0xe9'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test4, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test4:
|
||||
bez32 a0, .L.test4
|
||||
|
||||
# CHECK-ASM: bnez32 a0, .L.test5
|
||||
# CHECK-ASM: encoding: [0x20'A',0xe9'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test5, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test5:
|
||||
bnez32 a0, .L.test5
|
||||
|
||||
# CHECK-ASM: bhz32 a0, .L.test6
|
||||
# CHECK-ASM: encoding: [0x40'A',0xe9'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test6, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test6:
|
||||
bhz32 a0, .L.test6
|
||||
|
||||
# CHECK-ASM: blsz32 a0, .L.test7
|
||||
# CHECK-ASM: encoding: [0x60'A',0xe9'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test7, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test7:
|
||||
blsz32 a0, .L.test7
|
||||
|
||||
# CHECK-ASM: blz32 a0, .L.test8
|
||||
# CHECK-ASM: encoding: [0x80'A',0xe9'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test8, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test8:
|
||||
blz32 a0, .L.test8
|
||||
|
||||
# CHECK-ASM: bhsz32 a0, .L.test9
|
||||
# CHECK-ASM: encoding: [0xa0'A',0xe9'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test9, kind: fixup_csky_pcrel_imm16_scale2
|
||||
.L.test9:
|
||||
bhsz32 a0, .L.test9
|
||||
|
||||
# CHECK-ASM: jmp32 a3
|
||||
# CHECK-ASM: encoding: [0xc3,0xe8,0x00,0x00]
|
||||
jmp32 a3
|
||||
|
||||
# CHECK-ASM: jmpi32 .L.test10
|
||||
# CHECK-ASM: encoding: [0xc0'A',0xea'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test10, kind: fixup_csky_pcrel_uimm16_scale4
|
||||
.L.test10:
|
||||
jmpi32 [.L.test10]
|
||||
|
||||
# CHECK-ASM: bsr32 .L.test11
|
||||
# CHECK-ASM: encoding: [A,0xe0'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test11, kind: fixup_csky_pcrel_imm26_scale2
|
||||
.L.test11:
|
||||
bsr32 .L.test11
|
||||
|
||||
# CHECK-ASM: jsr32 a3
|
||||
# CHECK-ASM: encoding: [0xe3,0xe8,0x00,0x00]
|
||||
jsr32 a3
|
||||
|
||||
# CHECK-ASM: jsri32 .L.test12
|
||||
# CHECK-ASM: encoding: [0xe0'A',0xea'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test12, kind: fixup_csky_pcrel_uimm16_scale4
|
||||
.L.test12:
|
||||
jsri32 [.L.test12]
|
||||
|
||||
# CHECK-ASM: rts32
|
||||
# CHECK-ASM: encoding: [0xcf,0xe8,0x00,0x00]
|
||||
rts32
|
||||
|
||||
# CHECK-ASM: grs32 a0, .L.test13
|
||||
# CHECK-ASM: encoding: [0x0c'A',0xcc'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test13, kind: fixup_csky_pcrel_imm18_scale2
|
||||
.L.test13:
|
||||
grs32 a0, .L.test13
|
||||
|
||||
# CHECK-ASM: lrw32 a0, .L.test14
|
||||
# CHECK-ASM: encoding: [0x80'A',0xea'A',A,A]
|
||||
# CHECK-ASM: fixup A - offset: 0, value: .L.test14, kind: fixup_csky_pcrel_uimm16_scale4
|
||||
.L.test14:
|
||||
lrw32 a0, [.L.test14]
|
||||
|
||||
# RUN: not llvm-mc -triple csky --defsym=ERR=1 < %s 2>&1 | FileCheck %s
|
||||
|
||||
.ifdef ERR
|
||||
@ -308,4 +404,9 @@ subi32 t2, t3, 0x50, 0x60 # CHECK: :[[@LINE]]:22: error: invalid operand for ins
|
||||
xori32 a0, a1 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction
|
||||
xor32 a0, a2 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction
|
||||
|
||||
# Need label
|
||||
br32 0x100 # CHECK: :[[@LINE]]:6: error: operand must be a symbol name
|
||||
jmpi32 0x100 # CHECK: :[[@LINE]]:8: error: operand must be a constpool symbol name
|
||||
bsr32 0x100 # CHECK: :[[@LINE]]:7: error: operand must be a symbol name
|
||||
|
||||
.endif
|
||||
|
80
test/MC/CSKY/csky-error.s
Normal file
80
test/MC/CSKY/csky-error.s
Normal file
@ -0,0 +1,80 @@
|
||||
# RUN: not llvm-mc -triple=csky %s -filetype=obj -o %t.o 2>&1 | FileCheck %s
|
||||
|
||||
# Out of PC range
|
||||
|
||||
# br/bt/bf
|
||||
|
||||
.L.test1:
|
||||
.space 0x10001
|
||||
br32 .L.test1 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
|
||||
|
||||
br32 .L.test2 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
|
||||
.space 0x10001
|
||||
.L.test2:
|
||||
|
||||
.L.test3:
|
||||
.space 0xFFFF
|
||||
br32 .L.test3 # CHECK: :[[@LINE]]:1: error: fixup value must be 2-byte aligned
|
||||
|
||||
.L.test4:
|
||||
.space 0x10002
|
||||
br32 .L.test4 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
|
||||
# bsr
|
||||
.L.test5:
|
||||
.space 0x4000001
|
||||
bsr32 .L.test5 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
|
||||
|
||||
bsr32 .L.test6 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
|
||||
.space 0x4000001
|
||||
.L.test6:
|
||||
|
||||
.L.test7:
|
||||
.space 0x3FFFFFF
|
||||
bsr32 .L.test7 # CHECK: :[[@LINE]]:1: error: fixup value must be 2-byte aligned
|
||||
|
||||
.L.test8:
|
||||
.space 0x4000002
|
||||
bsr32 .L.test8 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
|
||||
# grs
|
||||
.L.test9:
|
||||
.space 0x40001
|
||||
grs32 a0, .L.test9 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
|
||||
|
||||
grs32 a0, .L.test10 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 2-byte aligned
|
||||
.space 0x40001
|
||||
.L.test10:
|
||||
|
||||
.L.test11:
|
||||
.space 0x3FFFF
|
||||
grs32 a0, .L.test11 # CHECK: :[[@LINE]]:1: error: fixup value must be 2-byte aligned
|
||||
|
||||
.L.test12:
|
||||
.space 0x40002
|
||||
grs32 a0, .L.test12 # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
|
||||
|
||||
# TODO: Fixup
|
||||
lrw32 a0, [.L.test15] # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 4-byte aligned
|
||||
.space 0x40001
|
||||
.L.test15:
|
||||
|
||||
# TODO: Fixup
|
||||
jsri32 [.L.test16] # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 4-byte aligned
|
||||
.space 0x40001
|
||||
.L.test16:
|
||||
|
||||
# TODO: Fixup
|
||||
jmpi32 [.L.test17] # CHECK: :[[@LINE]]:1: error: out of range pc-relative fixup value
|
||||
# CHECK: :[[@LINE-1]]:1: error: fixup value must be 4-byte aligned
|
||||
.space 0x40001
|
||||
.L.test17:
|
Loading…
Reference in New Issue
Block a user