This patch makes the assembler support all modifiers defined in gnu-as.
Also changes some diagnostic information.
Differential Revision: https://reviews.llvm.org/D132633
bool isUImm5() const { return isUImm<5>(); }
bool isUImm6() const { return isUImm<6>(); }
bool isUImm8() const { return isUImm<8>(); }
- bool isUImm12() const { return isUImm<12>(); }
- bool isUImm14() const { return isUImm<14>(); }
- bool isUImm15() const { return isUImm<15>(); }
+ bool isSImm12() const { return isSImm<12>(); }
+
+ bool isSImm12addlike() const {
+ if (!isImm())
+ return false;
+
+ int64_t Imm;
+ LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
+ return IsConstantImm
+ ? isInt<12>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
+ }
- bool isSImm12() const {
+ bool isSImm12lu52id() const {
if (!isImm())
return false;
int64_t Imm;
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
- bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_PCREL_LO;
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
+ return IsConstantImm
+ ? isInt<12>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
+ }
+
+ bool isUImm12() const { return isUImm<12>(); }
+ bool isUImm12ori() const {
+ if (!isImm())
+ return false;
+
+ int64_t Imm;
+ LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
return IsConstantImm
- ? (isInt<12>(Imm) &&
- (VK == LoongArchMCExpr::VK_LoongArch_None || IsValidKind))
- : (LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
- IsValidKind);
+ ? isUInt<12>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
}
+ bool isUImm14() const { return isUImm<14>(); }
+ bool isUImm15() const { return isUImm<15>(); }
+
bool isSImm14lsl2() const { return isSImm<14, 2>(); }
bool isSImm16() const { return isSImm<16>(); }
- bool isSImm16lsl2() const { return isSImm<16, 2>(); }
+
+ bool isSImm16lsl2() const {
+ if (!isImm())
+ return false;
+
+ int64_t Imm;
+ LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_B16;
+ return IsConstantImm
+ ? isShiftedInt<16, 2>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
+ }
+
bool isSImm20() const { return isSImm<20>(); }
bool isSImm20pcalau12i() const {
int64_t Imm;
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
- bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_PCREL_HI;
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
+ return IsConstantImm
+ ? isInt<20>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
+ }
+
+ bool isSImm20lu12iw() const {
+ if (!isImm())
+ return false;
+
+ int64_t Imm;
+ LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
+ return IsConstantImm
+ ? isInt<20>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
+ }
+
+ bool isSImm20lu32id() const {
+ if (!isImm())
+ return false;
+
+ int64_t Imm;
+ LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
return IsConstantImm
- ? (isInt<20>(Imm) &&
- (VK == LoongArchMCExpr::VK_LoongArch_None || IsValidKind))
- : (LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
- IsValidKind);
+ ? isInt<20>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
}
- bool isSImm21lsl2() const { return isSImm<21, 2>(); }
+ bool isSImm21lsl2() const {
+ if (!isImm())
+ return false;
- bool isSImm26Operand() const {
int64_t Imm;
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
- bool IsValidKind = (VK == LoongArchMCExpr::VK_LoongArch_CALL ||
- VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT);
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_B21;
+ return IsConstantImm
+ ? isShiftedInt<21, 2>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
+ }
+
+ bool isSImm26Operand() const {
+ if (!isImm())
+ return false;
+ int64_t Imm;
+ LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+ VK == LoongArchMCExpr::VK_LoongArch_CALL ||
+ VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT ||
+ VK == LoongArchMCExpr::VK_LoongArch_B26;
return IsConstantImm
- ? (isShiftedInt<26, 2>(Imm) &&
- (VK == LoongArchMCExpr::VK_LoongArch_None || IsValidKind))
- : (LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
- IsValidKind);
+ ? isShiftedInt<26, 2>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
}
/// Gets location of the first token of this operand.
case Match_InvalidUImm12:
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
/*Upper=*/(1 << 12) - 1);
+ case Match_InvalidUImm12ori:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, /*Lower=*/0,
+ /*Upper=*/(1 << 12) - 1,
+ "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
+ "integer in the range");
case Match_InvalidUImm15:
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
/*Upper=*/(1 << 15) - 1);
case Match_InvalidSImm12:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
+ /*Upper=*/(1 << 11) - 1);
+ case Match_InvalidSImm12addlike:
return generateImmOutOfRangeError(
Operands, ErrorInfo, /*Lower=*/-(1 << 11),
/*Upper=*/(1 << 11) - 1,
"operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
"in the range");
+ case Match_InvalidSImm12lu52id:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, /*Lower=*/-(1 << 11),
+ /*Upper=*/(1 << 11) - 1,
+ "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
+ "integer in the range");
case Match_InvalidSImm14lsl2:
return generateImmOutOfRangeError(
Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
case Match_InvalidSImm16lsl2:
return generateImmOutOfRangeError(
Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
- "immediate must be a multiple of 4 in the range");
+ "operand must be a symbol with modifier (e.g. %b16) or an integer "
+ "in the range");
case Match_InvalidSImm20:
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
/*Upper=*/(1 << 19) - 1);
+ case Match_InvalidSImm20lu12iw:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, /*Lower=*/-(1 << 19),
+ /*Upper=*/(1 << 19) - 1,
+ "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
+ "in the range");
+ case Match_InvalidSImm20lu32id:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, /*Lower=*/-(1 << 19),
+ /*Upper=*/(1 << 19) - 1,
+ "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
+ "integer in the range");
case Match_InvalidSImm20pcalau12i:
return generateImmOutOfRangeError(
Operands, ErrorInfo, /*Lower=*/-(1 << 19),
case Match_InvalidSImm21lsl2:
return generateImmOutOfRangeError(
Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
- "immediate must be a multiple of 4 in the range");
+ "operand must be a symbol with modifier (e.g. %b21) or an integer "
+ "in the range");
case Match_InvalidSImm26Operand:
return generateImmOutOfRangeError(
Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,
let ParserMatchClass = UImmAsmOperand<8>;
}
-def uimm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<12>(Imm);}]> {
+class UImm12Operand : Operand<GRLenVT>,
+ ImmLeaf <GRLenVT, [{return isUInt<12>(Imm);}]> {
+ let DecoderMethod = "decodeUImmOperand<12>";
+}
+
+def uimm12 : UImm12Operand {
let ParserMatchClass = UImmAsmOperand<12>;
}
+def uimm12_ori : UImm12Operand {
+ let ParserMatchClass = UImmAsmOperand<12, "ori">;
+}
+
def uimm14 : Operand<GRLenVT> {
let ParserMatchClass = UImmAsmOperand<14>;
}
let ParserMatchClass = UImmAsmOperand<15>;
}
-def simm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isInt<12>(Imm);}]> {
- let ParserMatchClass = SImmAsmOperand<12>;
+class SImm12Operand : Operand<GRLenVT>,
+ ImmLeaf <GRLenVT, [{return isInt<12>(Imm);}]> {
let DecoderMethod = "decodeSImmOperand<12>";
}
+def simm12 : SImm12Operand {
+ let ParserMatchClass = SImmAsmOperand<12>;
+}
+
+def simm12_addlike : SImm12Operand {
+ let ParserMatchClass = SImmAsmOperand<12, "addlike">;
+}
+
+def simm12_lu52id : SImm12Operand {
+ let ParserMatchClass = SImmAsmOperand<12, "lu52id">;
+}
+
def simm14_lsl2 : Operand<GRLenVT>,
ImmLeaf<GRLenVT, [{return isShiftedInt<14,2>(Imm);}]> {
let ParserMatchClass = SImmAsmOperand<14, "lsl2">;
let ParserMatchClass = SImmAsmOperand<20, "pcalau12i">;
}
+def simm20_lu12iw : SImm20Operand {
+ let ParserMatchClass = SImmAsmOperand<20, "lu12iw">;
+}
+
+def simm20_lu32id : SImm20Operand {
+ let ParserMatchClass = SImmAsmOperand<20, "lu32id">;
+}
+
def simm21_lsl2 : Operand<OtherVT> {
let ParserMatchClass = SImmAsmOperand<21, "lsl2">;
let EncoderMethod = "getImmOpValueAsr2";
class LOAD_3R<bits<17> op, string opstr>
: Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
class LOAD_2RI12<bits<10> op, string opstr>
- : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12:$imm12), opstr,
+ : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12_addlike:$imm12), opstr,
"$rd, $rj, $imm12">;
class LOAD_2RI14<bits<8> op, string opstr>
: Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr,
: Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk), opstr,
"$rd, $rj, $rk">;
class STORE_2RI12<bits<10> op, string opstr>
- : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12:$imm12), opstr,
+ : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12_addlike:$imm12), opstr,
"$rd, $rj, $imm12">;
class STORE_2RI14<bits<8> op, string opstr>
: Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), opstr,
// Arithmetic Operation Instructions
def ADD_W : ALU_3R<0b00000000000100000, "add.w">;
def SUB_W : ALU_3R<0b00000000000100010, "sub.w">;
-def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12>;
+def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12_addlike>;
def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>;
-def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20>;
+def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20_lu12iw>;
def SLT : ALU_3R<0b00000000000100100, "slt">;
def SLTU : ALU_3R<0b00000000000100101, "sltu">;
def SLTI : ALU_2RI12<0b0000001000, "slti", simm12>;
def ANDN : ALU_3R<0b00000000000101101, "andn">;
def ORN : ALU_3R<0b00000000000101100, "orn">;
def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>;
-def ORI : ALU_2RI12<0b0000001110, "ori", uimm12>;
+def ORI : ALU_2RI12<0b0000001110, "ori", uimm12_ori>;
def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>;
def MUL_W : ALU_3R<0b00000000000111000, "mul.w">;
def MULH_W : ALU_3R<0b00000000000111001, "mulh.w">;
// Arithmetic Operation Instructions for 64-bits
def ADD_D : ALU_3R<0b00000000000100001, "add.d">;
def SUB_D : ALU_3R<0b00000000000100011, "sub.d">;
-def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12>;
+def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12_addlike>;
def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>;
def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>;
def ALSL_D : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>;
let Constraints = "$rd = $dst" in {
def LU32I_D : Fmt1RI20<0b0001011, (outs GPR:$dst),
- (ins GPR:$rd, simm20:$imm20), "lu32i.d",
+ (ins GPR:$rd, simm20_lu32id:$imm20), "lu32i.d",
"$rd, $imm20">;
}
-def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12>;
+def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12_lu52id>;
def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>;
def MUL_D : ALU_3R<0b00000000000111011, "mul.d">;
def MULH_D : ALU_3R<0b00000000000111100, "mulh.d">;
Kind = LoongArchMCExpr::VK_LoongArch_CALL_PLT;
break;
case LoongArchII::MO_PCREL_HI:
- Kind = LoongArchMCExpr::VK_LoongArch_PCREL_HI;
+ Kind = LoongArchMCExpr::VK_LoongArch_PCALA_HI20;
break;
case LoongArchII::MO_PCREL_LO:
- Kind = LoongArchMCExpr::VK_LoongArch_PCREL_LO;
+ Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
break;
// TODO: Handle more target-flags.
}
// LoongArchFixupKinds.h.
//
// {name, offset, bits, flags}
- {"fixup_loongarch_b26", 0, 26, 0},
- {"fixup_loongarch_pcala_hi20", 5, 20, MCFixupKindInfo::FKF_IsPCRel},
- {"fixup_loongarch_pcala_lo12", 10, 12, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_loongarch_b16", 10, 16, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_loongarch_b21", 0, 26, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_loongarch_b26", 0, 26, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_loongarch_abs_hi20", 5, 20, 0},
+ {"fixup_loongarch_abs_lo12", 10, 12, 0},
+ {"fixup_loongarch_abs64_lo20", 5, 20, 0},
+ {"fixup_loongarch_abs64_hi12", 10, 12, 0},
+ {"fixup_loongarch_tls_le_hi20", 5, 20, 0},
+ {"fixup_loongarch_tls_le_lo12", 10, 12, 0},
+ {"fixup_loongarch_tls_le64_lo20", 5, 20, 0},
+ {"fixup_loongarch_tls_le64_hi12", 10, 12, 0},
// TODO: Add more fixup kinds.
};
return ELF::R_LARCH_32;
case FK_Data_8:
return ELF::R_LARCH_64;
- case LoongArch::fixup_loongarch_pcala_hi20:
- return ELF::R_LARCH_PCALA_HI20;
- case LoongArch::fixup_loongarch_pcala_lo12:
- return ELF::R_LARCH_PCALA_LO12;
+ case LoongArch::fixup_loongarch_b16:
+ return ELF::R_LARCH_B16;
+ case LoongArch::fixup_loongarch_b21:
+ return ELF::R_LARCH_B21;
case LoongArch::fixup_loongarch_b26:
return ELF::R_LARCH_B26;
+ case LoongArch::fixup_loongarch_abs_hi20:
+ return ELF::R_LARCH_ABS_HI20;
+ case LoongArch::fixup_loongarch_abs_lo12:
+ return ELF::R_LARCH_ABS_LO12;
+ case LoongArch::fixup_loongarch_abs64_lo20:
+ return ELF::R_LARCH_ABS64_LO20;
+ case LoongArch::fixup_loongarch_abs64_hi12:
+ return ELF::R_LARCH_ABS64_HI12;
+ case LoongArch::fixup_loongarch_tls_le_hi20:
+ return ELF::R_LARCH_TLS_LE_HI20;
+ case LoongArch::fixup_loongarch_tls_le_lo12:
+ return ELF::R_LARCH_TLS_LE_LO12;
+ case LoongArch::fixup_loongarch_tls_le64_lo20:
+ return ELF::R_LARCH_TLS_LE64_LO20;
+ case LoongArch::fixup_loongarch_tls_le64_hi12:
+ return ELF::R_LARCH_TLS_LE64_HI12;
// TODO: Handle more fixup-kinds.
}
}
#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHFIXUPKINDS_H
#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHFIXUPKINDS_H
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCFixup.h"
#undef LoongArch
// LoongArchAsmBackend.cpp.
//
enum Fixups {
- // 26-bit fixup for symbol references in the b/bl instructions.
- fixup_loongarch_b26 = FirstTargetFixupKind,
- // 20-bit fixup corresponding to %pc_hi20(foo) for instruction pcalau12i.
- fixup_loongarch_pcala_hi20,
- // 12-bit fixup corresponding to %pc_lo12(foo) for instructions addi.w/d.
- fixup_loongarch_pcala_lo12,
+ // Define fixups can be handled by LoongArchAsmBackend::applyFixup.
+ // 16-bit fixup corresponding to %b16(foo) for instructions like bne.
+ fixup_loongarch_b16 = FirstTargetFixupKind,
+ // 21-bit fixup corresponding to %b21(foo) for instructions like bnez.
+ fixup_loongarch_b21,
+ // 26-bit fixup corresponding to %b26(foo)/%plt(foo) for instructions b/bl.
+ fixup_loongarch_b26,
+ // 20-bit fixup corresponding to %abs_hi20(foo) for instruction lu12i.w.
+ fixup_loongarch_abs_hi20,
+ // 12-bit fixup corresponding to %abs_lo12(foo) for instruction ori.
+ fixup_loongarch_abs_lo12,
+ // 20-bit fixup corresponding to %abs64_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_abs64_lo20,
+ // 12-bit fixup corresponding to %abs_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_abs64_hi12,
+ // 20-bit fixup corresponding to %le_hi20(foo) for instruction lu12i.w.
+ fixup_loongarch_tls_le_hi20,
+ // 12-bit fixup corresponding to %le_lo12(foo) for instruction ori.
+ fixup_loongarch_tls_le_lo12,
+ // 20-bit fixup corresponding to %le64_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_tls_le64_lo20,
+ // 12-bit fixup corresponding to %le64_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_tls_le64_hi12,
// TODO: Add more fixup kind.
- // Used as a sentinel, must be the last.
+ // Used as a sentinel, must be the last of the fixup which can be handled by
+ // LoongArchAsmBackend::applyFixup.
fixup_loongarch_invalid,
- NumTargetFixupKinds = fixup_loongarch_invalid - FirstTargetFixupKind
+ NumTargetFixupKinds = fixup_loongarch_invalid - FirstTargetFixupKind,
+
+ // Define fixups for force relocation as FirstLiteralRelocationKind+V
+ // represents the relocation type with number V.
+ // 20-bit fixup corresponding to %pc_hi20(foo) for instruction pcalau12i.
+ fixup_loongarch_pcala_hi20 =
+ FirstLiteralRelocationKind + ELF::R_LARCH_PCALA_HI20,
+ // 12-bit fixup corresponding to %pc_lo12(foo) for instructions like addi.w/d.
+ fixup_loongarch_pcala_lo12,
+ // 20-bit fixup corresponding to %pc64_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_pcala64_lo20,
+ // 12-bit fixup corresponding to %pc64_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_pcala64_hi12,
+ // 20-bit fixup corresponding to %got_pc_hi20(foo) for instruction pcalau12i.
+ fixup_loongarch_got_pc_hi20,
+ // 12-bit fixup corresponding to %got_pc_lo12(foo) for instructions
+ // ld.w/ld.d/add.d.
+ fixup_loongarch_got_pc_lo12,
+ // 20-bit fixup corresponding to %got64_pc_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_got64_pc_lo20,
+ // 12-bit fixup corresponding to %got64_pc_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_got64_pc_hi12,
+ // 20-bit fixup corresponding to %got_hi20(foo) for instruction lu12i.w.
+ fixup_loongarch_got_hi20,
+ // 12-bit fixup corresponding to %got_lo12(foo) for instruction ori.
+ fixup_loongarch_got_lo12,
+ // 20-bit fixup corresponding to %got64_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_got64_lo20,
+ // 12-bit fixup corresponding to %got64_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_got64_hi12,
+ // Skip R_LARCH_TLS_LE_*.
+ // 20-bit fixup corresponding to %ie_pc_hi20(foo) for instruction pcalau12i.
+ fixup_loongarch_tls_ie_pc_hi20 =
+ FirstLiteralRelocationKind + ELF::R_LARCH_TLS_IE_PC_HI20,
+ // 12-bit fixup corresponding to %ie_pc_lo12(foo) for instructions
+ // ld.w/ld.d/add.d.
+ fixup_loongarch_tls_ie_pc_lo12,
+ // 20-bit fixup corresponding to %ie64_pc_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_tls_ie64_pc_lo20,
+ // 12-bit fixup corresponding to %ie64_pc_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_tls_ie64_pc_hi12,
+ // 20-bit fixup corresponding to %ie_hi20(foo) for instruction lu12i.w.
+ fixup_loongarch_tls_ie_hi20,
+ // 12-bit fixup corresponding to %ie_lo12(foo) for instruction ori.
+ fixup_loongarch_tls_ie_lo12,
+ // 20-bit fixup corresponding to %ie64_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_tls_ie64_lo20,
+ // 12-bit fixup corresponding to %ie64_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_tls_ie64_hi12,
+ // 20-bit fixup corresponding to %ld_pc_hi20(foo) for instruction pcalau12i.
+ fixup_loongarch_tls_ld_pc_hi20,
+ // 20-bit fixup corresponding to %ld_hi20(foo) for instruction lu12i.w.
+ fixup_loongarch_tls_ld_hi20,
+ // 20-bit fixup corresponding to %gd_pc_hi20(foo) for instruction pcalau12i.
+ fixup_loongarch_tls_gd_pc_hi20,
+ // 20-bit fixup corresponding to %gd_hi20(foo) for instruction lu12i.w.
+ fixup_loongarch_tls_gd_hi20
};
} // end namespace LoongArch
} // end namespace llvm
case LoongArchMCExpr::VK_LoongArch_None:
case LoongArchMCExpr::VK_LoongArch_Invalid:
llvm_unreachable("Unhandled fixup kind!");
- case LoongArchMCExpr::VK_LoongArch_PCREL_HI:
- FixupKind = LoongArch::fixup_loongarch_pcala_hi20;
+ case LoongArchMCExpr::VK_LoongArch_B16:
+ FixupKind = LoongArch::fixup_loongarch_b16;
break;
- case LoongArchMCExpr::VK_LoongArch_PCREL_LO:
- FixupKind = LoongArch::fixup_loongarch_pcala_lo12;
+ case LoongArchMCExpr::VK_LoongArch_B21:
+ FixupKind = LoongArch::fixup_loongarch_b21;
break;
+ case LoongArchMCExpr::VK_LoongArch_B26:
case LoongArchMCExpr::VK_LoongArch_CALL:
case LoongArchMCExpr::VK_LoongArch_CALL_PLT:
FixupKind = LoongArch::fixup_loongarch_b26;
break;
+ case LoongArchMCExpr::VK_LoongArch_ABS_HI20:
+ FixupKind = LoongArch::fixup_loongarch_abs_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_ABS_LO12:
+ FixupKind = LoongArch::fixup_loongarch_abs_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_ABS64_LO20:
+ FixupKind = LoongArch::fixup_loongarch_abs64_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_ABS64_HI12:
+ FixupKind = LoongArch::fixup_loongarch_abs64_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_PCALA_HI20:
+ FixupKind = LoongArch::fixup_loongarch_pcala_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_PCALA_LO12:
+ FixupKind = LoongArch::fixup_loongarch_pcala_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_PCALA64_LO20:
+ FixupKind = LoongArch::fixup_loongarch_pcala64_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_PCALA64_HI12:
+ FixupKind = LoongArch::fixup_loongarch_pcala64_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20:
+ FixupKind = LoongArch::fixup_loongarch_got_pc_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12:
+ FixupKind = LoongArch::fixup_loongarch_got_pc_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20:
+ FixupKind = LoongArch::fixup_loongarch_got64_pc_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12:
+ FixupKind = LoongArch::fixup_loongarch_got64_pc_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_GOT_HI20:
+ FixupKind = LoongArch::fixup_loongarch_got_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_GOT_LO12:
+ FixupKind = LoongArch::fixup_loongarch_got_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_GOT64_LO20:
+ FixupKind = LoongArch::fixup_loongarch_got64_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_GOT64_HI12:
+ FixupKind = LoongArch::fixup_loongarch_got64_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_le_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12:
+ FixupKind = LoongArch::fixup_loongarch_tls_le_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20:
+ FixupKind = LoongArch::fixup_loongarch_tls_le64_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12:
+ FixupKind = LoongArch::fixup_loongarch_tls_le64_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12:
+ FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20:
+ FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12:
+ FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_ie_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12:
+ FixupKind = LoongArch::fixup_loongarch_tls_ie_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20:
+ FixupKind = LoongArch::fixup_loongarch_tls_ie64_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12:
+ FixupKind = LoongArch::fixup_loongarch_tls_ie64_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_ld_pc_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_ld_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_gd_pc_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_gd_hi20;
+ break;
+ }
+ } else if (Kind == MCExpr::SymbolRef &&
+ cast<MCSymbolRefExpr>(Expr)->getKind() ==
+ MCSymbolRefExpr::VK_None) {
+ switch (MI.getOpcode()) {
+ default:
+ break;
+ case LoongArch::BEQ:
+ case LoongArch::BNE:
+ case LoongArch::BLT:
+ case LoongArch::BGE:
+ case LoongArch::BLTU:
+ case LoongArch::BGEU:
+ FixupKind = LoongArch::fixup_loongarch_b16;
+ break;
+ case LoongArch::BEQZ:
+ case LoongArch::BNEZ:
+ case LoongArch::BCEQZ:
+ case LoongArch::BCNEZ:
+ FixupKind = LoongArch::fixup_loongarch_b21;
+ break;
}
}
llvm_unreachable("Invalid ELF symbol kind");
case VK_LoongArch_CALL_PLT:
return "plt";
- case VK_LoongArch_PCREL_HI:
+ case VK_LoongArch_B16:
+ return "b16";
+ case VK_LoongArch_B21:
+ return "b21";
+ case VK_LoongArch_B26:
+ return "b21";
+ case VK_LoongArch_ABS_HI20:
+ return "abs_hi20";
+ case VK_LoongArch_ABS_LO12:
+ return "abs_lo12";
+ case VK_LoongArch_ABS64_LO20:
+ return "abs64_lo20";
+ case VK_LoongArch_ABS64_HI12:
+ return "abs64_hi12";
+ case VK_LoongArch_PCALA_HI20:
return "pc_hi20";
- case VK_LoongArch_PCREL_LO:
+ case VK_LoongArch_PCALA_LO12:
return "pc_lo12";
+ case VK_LoongArch_PCALA64_LO20:
+ return "pc64_lo20";
+ case VK_LoongArch_PCALA64_HI12:
+ return "pc64_hi12";
+ case VK_LoongArch_GOT_PC_HI20:
+ return "got_pc_hi20";
+ case VK_LoongArch_GOT_PC_LO12:
+ return "got_pc_lo12";
+ case VK_LoongArch_GOT64_PC_LO20:
+ return "got64_pc_lo20";
+ case VK_LoongArch_GOT64_PC_HI12:
+ return "got64_pc_hi12";
+ case VK_LoongArch_GOT_HI20:
+ return "got_hi20";
+ case VK_LoongArch_GOT_LO12:
+ return "got_lo12";
+ case VK_LoongArch_GOT64_LO20:
+ return "got64_lo20";
+ case VK_LoongArch_GOT64_HI12:
+ return "got64_hi12";
+ case VK_LoongArch_TLS_LE_HI20:
+ return "le_hi20";
+ case VK_LoongArch_TLS_LE_LO12:
+ return "le_lo12";
+ case VK_LoongArch_TLS_LE64_LO20:
+ return "le64_lo20";
+ case VK_LoongArch_TLS_LE64_HI12:
+ return "le64_hi12";
+ case VK_LoongArch_TLS_IE_PC_HI20:
+ return "ie_pc_hi20";
+ case VK_LoongArch_TLS_IE_PC_LO12:
+ return "ie_pc_lo12";
+ case VK_LoongArch_TLS_IE64_PC_LO20:
+ return "ie64_pc_lo20";
+ case VK_LoongArch_TLS_IE64_PC_HI12:
+ return "ie64_pc_hi12";
+ case VK_LoongArch_TLS_IE_HI20:
+ return "ie_hi20";
+ case VK_LoongArch_TLS_IE_LO12:
+ return "ie_lo12";
+ case VK_LoongArch_TLS_IE64_LO20:
+ return "ie64_lo20";
+ case VK_LoongArch_TLS_IE64_HI12:
+ return "ie64_hi12";
+ case VK_LoongArch_TLS_LD_PC_HI20:
+ return "ld_pc_hi20";
+ case VK_LoongArch_TLS_LD_HI20:
+ return "ld_hi20";
+ case VK_LoongArch_TLS_GD_PC_HI20:
+ return "gd_pc_hi20";
+ case VK_LoongArch_TLS_GD_HI20:
+ return "gd_hi20";
}
}
LoongArchMCExpr::VariantKind
LoongArchMCExpr::getVariantKindForName(StringRef name) {
return StringSwitch<LoongArchMCExpr::VariantKind>(name)
- .Case("pc_hi20", VK_LoongArch_PCREL_HI)
- .Case("pc_lo12", VK_LoongArch_PCREL_LO)
.Case("plt", VK_LoongArch_CALL_PLT)
+ .Case("b16", VK_LoongArch_B16)
+ .Case("b21", VK_LoongArch_B21)
+ .Case("b26", VK_LoongArch_B26)
+ .Case("abs_hi20", VK_LoongArch_ABS_HI20)
+ .Case("abs_lo12", VK_LoongArch_ABS_LO12)
+ .Case("abs64_lo20", VK_LoongArch_ABS64_LO20)
+ .Case("abs64_hi12", VK_LoongArch_ABS64_HI12)
+ .Case("pc_hi20", VK_LoongArch_PCALA_HI20)
+ .Case("pc_lo12", VK_LoongArch_PCALA_LO12)
+ .Case("pc64_lo20", VK_LoongArch_PCALA64_LO20)
+ .Case("pc64_hi12", VK_LoongArch_PCALA64_HI12)
+ .Case("got_pc_hi20", VK_LoongArch_GOT_PC_HI20)
+ .Case("got_pc_lo12", VK_LoongArch_GOT_PC_LO12)
+ .Case("got64_pc_lo20", VK_LoongArch_GOT64_PC_LO20)
+ .Case("got64_pc_hi12", VK_LoongArch_GOT64_PC_HI12)
+ .Case("got_hi20", VK_LoongArch_GOT_HI20)
+ .Case("got_lo12", VK_LoongArch_GOT_LO12)
+ .Case("got64_lo20", VK_LoongArch_GOT64_LO20)
+ .Case("got64_hi12", VK_LoongArch_GOT64_HI12)
+ .Case("le_hi20", VK_LoongArch_TLS_LE_HI20)
+ .Case("le_lo12", VK_LoongArch_TLS_LE_LO12)
+ .Case("le64_lo20", VK_LoongArch_TLS_LE64_LO20)
+ .Case("le64_hi12", VK_LoongArch_TLS_LE64_HI12)
+ .Case("ie_pc_hi20", VK_LoongArch_TLS_IE_PC_HI20)
+ .Case("ie_pc_lo12", VK_LoongArch_TLS_IE_PC_LO12)
+ .Case("ie64_pc_lo20", VK_LoongArch_TLS_IE64_PC_LO20)
+ .Case("ie64_pc_hi12", VK_LoongArch_TLS_IE64_PC_HI12)
+ .Case("ie_hi20", VK_LoongArch_TLS_IE_HI20)
+ .Case("ie_lo12", VK_LoongArch_TLS_IE_LO12)
+ .Case("ie64_lo20", VK_LoongArch_TLS_IE64_LO20)
+ .Case("ie64_hi12", VK_LoongArch_TLS_IE64_HI12)
+ .Case("ld_pc_hi20", VK_LoongArch_TLS_LD_PC_HI20)
+ .Case("ld_hi20", VK_LoongArch_TLS_LD_HI20)
+ .Case("gd_pc_hi20", VK_LoongArch_TLS_GD_PC_HI20)
+ .Case("gd_hi20", VK_LoongArch_TLS_GD_HI20)
.Default(VK_LoongArch_Invalid);
}
class LoongArchMCExpr : public MCTargetExpr {
public:
enum VariantKind {
- // TODO: Add more target kinds.
VK_LoongArch_None,
VK_LoongArch_CALL,
VK_LoongArch_CALL_PLT,
- VK_LoongArch_PCREL_HI,
- VK_LoongArch_PCREL_LO,
+ VK_LoongArch_B16,
+ VK_LoongArch_B21,
+ VK_LoongArch_B26,
+ VK_LoongArch_ABS_HI20,
+ VK_LoongArch_ABS_LO12,
+ VK_LoongArch_ABS64_LO20,
+ VK_LoongArch_ABS64_HI12,
+ VK_LoongArch_PCALA_HI20,
+ VK_LoongArch_PCALA_LO12,
+ VK_LoongArch_PCALA64_LO20,
+ VK_LoongArch_PCALA64_HI12,
+ VK_LoongArch_GOT_PC_HI20,
+ VK_LoongArch_GOT_PC_LO12,
+ VK_LoongArch_GOT64_PC_LO20,
+ VK_LoongArch_GOT64_PC_HI12,
+ VK_LoongArch_GOT_HI20,
+ VK_LoongArch_GOT_LO12,
+ VK_LoongArch_GOT64_LO20,
+ VK_LoongArch_GOT64_HI12,
+ VK_LoongArch_TLS_LE_HI20,
+ VK_LoongArch_TLS_LE_LO12,
+ VK_LoongArch_TLS_LE64_LO20,
+ VK_LoongArch_TLS_LE64_HI12,
+ VK_LoongArch_TLS_IE_PC_HI20,
+ VK_LoongArch_TLS_IE_PC_LO12,
+ VK_LoongArch_TLS_IE64_PC_LO20,
+ VK_LoongArch_TLS_IE64_PC_HI12,
+ VK_LoongArch_TLS_IE_HI20,
+ VK_LoongArch_TLS_IE_LO12,
+ VK_LoongArch_TLS_IE64_LO20,
+ VK_LoongArch_TLS_IE64_HI12,
+ VK_LoongArch_TLS_LD_PC_HI20,
+ VK_LoongArch_TLS_LD_HI20,
+ VK_LoongArch_TLS_GD_PC_HI20,
+ VK_LoongArch_TLS_GD_HI20,
VK_LoongArch_Invalid // Must be the last item.
};
## Test invalid instructions on both loongarch32 and loongarch64 target.
-# RUN: not llvm-mc --triple=loongarch32 --mattr=-f %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK64
-# RUN: not llvm-mc --triple=loongarch64 --mattr=-f %s 2>&1 --defsym=LA64=1 | FileCheck %s
+# RUN: not llvm-mc --triple=loongarch32 --mattr=-f %s 2>&1 \
+# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK64
+# RUN: not llvm-mc --triple=loongarch64 --mattr=-f %s 2>&1 --defsym=LA64=1 \
+# RUN: | FileCheck %s
## Out of range immediates
## uimm2
## uimm12
andi $a0, $a0, -1
# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [0, 4095]
-ori $a0, $a0, 4096
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be an integer in the range [0, 4095]
xori $a0, $a0, 4096
# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [0, 4095]
+## uimm12_ori
+ori $a0, $a0, 4096
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %abs_lo12) or an integer in the range [0, 4095]
+
## simm12
-addi.w $a0, $a0, -2049
-# CHECK: :[[#@LINE-1]]:18: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
slti $a0, $a0, -2049
-# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
sltui $a0, $a0, 2048
-# CHECK: :[[#@LINE-1]]:17: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
+# CHECK: :[[#@LINE-1]]:17: error: immediate must be an integer in the range [-2048, 2047]
preld 0, $a0, 2048
-# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
+# CHECK: :[[#@LINE-1]]:15: error: immediate must be an integer in the range [-2048, 2047]
+
+## simm12_addlike
+addi.w $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:18: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
ld.b $a0, $a0, 2048
# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
ld.h $a0, $a0, 2048
## simm16_lsl2
beq $a0, $a0, -0x20004
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
bne $a0, $a0, -0x20004
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
blt $a0, $a0, -0x1FFFF
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
bge $a0, $a0, -0x1FFFF
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
bltu $a0, $a0, 0x1FFFF
-# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
bgeu $a0, $a0, 0x1FFFF
-# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
jirl $a0, $a0, 0x20000
-# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
## simm20
-lu12i.w $a0, -0x80001
-# CHECK: :[[#@LINE-1]]:14: error: immediate must be an integer in the range [-524288, 524287]
pcaddi $a0, -0x80001
# CHECK: :[[#@LINE-1]]:13: error: immediate must be an integer in the range [-524288, 524287]
pcaddu12i $a0, 0x80000
# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]
+## simm20_lu12iw
+lu12i.w $a0, -0x80001
+# CHECK: :[[#@LINE-1]]:14: error: operand must be a symbol with modifier (e.g. %abs_hi20) or an integer in the range [-524288, 524287]
+
## simm20_pcalau12i
pcalau12i $a0, 0x80000
# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pc_hi20) or an integer in the range [-524288, 524287]
## simm21_lsl2
beqz $a0, -0x400001
-# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a symbol with modifier (e.g. %b21) or an integer in the range [-4194304, 4194300]
bnez $a0, -0x3FFFFF
-# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a symbol with modifier (e.g. %b21) or an integer in the range [-4194304, 4194300]
beqz $a0, 0x3FFFFF
-# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a symbol with modifier (e.g. %b21) or an integer in the range [-4194304, 4194300]
bnez $a0, 0x400000
-# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a symbol with modifier (e.g. %b21) or an integer in the range [-4194304, 4194300]
## simm26_lsl2
b -0x8000001
bstrpick.d $a0, $a0, 64, 0
# CHECK: :[[#@LINE-1]]:22: error: immediate must be an integer in the range [0, 63]
-## simm12
+## simm12_addlike
addi.d $a0, $a0, -2049
# CHECK: :[[#@LINE-1]]:18: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
-lu52i.d $a0, $a0, -2049
-# CHECK: :[[#@LINE-1]]:19: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
ld.wu $a0, $a0, 2048
# CHECK: :[[#@LINE-1]]:17: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
ld.d $a0, $a0, 2048
st.d $a0, $a0, 2048
# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
+## simm12_lu52id
+lu52i.d $a0, $a0, 2048
+# CHECK-LA64: :[[#@LINE-1]]:19: error: operand must be a symbol with modifier (e.g. %pc64_hi12) or an integer in the range [-2048, 2047]
+
## simm14_lsl2
ldptr.w $a0, $a0, -32772
# CHECK: :[[#@LINE-1]]:19: error: immediate must be a multiple of 4 in the range [-32768, 32764]
# CHECK: :[[#@LINE-1]]:21: error: immediate must be an integer in the range [-32768, 32767]
## simm20
-lu32i.d $a0, -0x80001
-# CHECK: :[[#@LINE-1]]:14: error: immediate must be an integer in the range [-524288, 524287]
pcaddu18i $a0, 0x80000
# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]
+## simm20_lu32id
+lu32i.d $a0, 0x80000
+# CHECK-LA64: :[[#@LINE-1]]:14: error: operand must be a symbol with modifier (e.g. %abs64_lo20) or an integer in the range [-524288, 524287]
+
## msbd < lsbd
# CHECK: :[[#@LINE+1]]:21: error: msb is less than lsb
bstrins.d $a0, $a0, 1, 2
.quad foo
# RELOC: R_LARCH_64 foo
+bne $t1, $t2, %b16(foo)
+# RELOC: R_LARCH_B16
+# INSTR: bne $t1, $t2, %b16(foo)
+# FIXUP: fixup A - offset: 0, value: %b16(foo), kind: fixup_loongarch_b16
+
+bnez $t1, %b21(foo)
+# RELOC: R_LARCH_B21
+# INSTR: bnez $t1, %b21(foo)
+# FIXUP: fixup A - offset: 0, value: %b21(foo), kind: fixup_loongarch_b21
+
+bl %plt(foo)
+# RELOC: R_LARCH_B26
+# INSTR: bl %plt(foo)
+# FIXUP: fixup A - offset: 0, value: %plt(foo), kind: fixup_loongarch_b26
+
+bl foo
+# RELOC: R_LARCH_B26
+# INSTR: bl foo
+# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_loongarch_b26
+
+lu12i.w $t1, %abs_hi20(foo)
+# RELOC: R_LARCH_ABS_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %abs_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %abs_hi20(foo), kind: fixup_loongarch_abs_hi20
+
+ori $t1, $t1, %abs_lo12(foo)
+# RELOC: R_LARCH_ABS_LO12 foo 0x0
+# INSTR: ori $t1, $t1, %abs_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %abs_lo12(foo), kind: fixup_loongarch_abs_lo12
+
+lu32i.d $t1, %abs64_lo20(foo)
+# RELOC: R_LARCH_ABS64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %abs64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %abs64_lo20(foo), kind: fixup_loongarch_abs64_lo20
+
+lu52i.d $t1, $t1, %abs64_hi12(foo)
+# RELOC: R_LARCH_ABS64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %abs64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %abs64_hi12(foo), kind: fixup_loongarch_abs64_hi12
+
pcalau12i $t1, %pc_hi20(foo)
# RELOC: R_LARCH_PCALA_HI20 foo 0x0
# INSTR: pcalau12i $t1, %pc_hi20(foo)
-# FIXUP: fixup A - offset: 0, value: %pc_hi20(foo), kind: fixup_loongarch_pcala_hi20
+# FIXUP: fixup A - offset: 0, value: %pc_hi20(foo), kind: FK_NONE
pcalau12i $t1, %pc_hi20(foo+4)
# RELOC: R_LARCH_PCALA_HI20 foo 0x4
# INSTR: pcalau12i $t1, %pc_hi20(foo+4)
-# FIXUP: fixup A - offset: 0, value: %pc_hi20(foo+4), kind: fixup_loongarch_pcala_hi20
+# FIXUP: fixup A - offset: 0, value: %pc_hi20(foo+4), kind: FK_NONE
addi.d $t1, $t1, %pc_lo12(foo)
# RELOC: R_LARCH_PCALA_LO12 foo 0x0
# INSTR: addi.d $t1, $t1, %pc_lo12(foo)
-# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo), kind: fixup_loongarch_pcala_lo12
+# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo), kind: FK_NONE
addi.d $t1, $t1, %pc_lo12(foo+4)
# RELOC: R_LARCH_PCALA_LO12 foo 0x4
# INSTR: addi.d $t1, $t1, %pc_lo12(foo+4)
-# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo+4), kind: fixup_loongarch_pcala_lo12
+# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo+4), kind: FK_NONE
st.b $t1, $a2, %pc_lo12(foo)
# RELOC: R_LARCH_PCALA_LO12 foo 0x0
# INSTR: st.b $t1, $a2, %pc_lo12(foo)
-# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo), kind: fixup_loongarch_pcala_lo12
+# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo), kind: FK_NONE
st.b $t1, $a2, %pc_lo12(foo+4)
# RELOC: R_LARCH_PCALA_LO12 foo 0x4
# INSTR: st.b $t1, $a2, %pc_lo12(foo+4)
-# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo+4), kind: fixup_loongarch_pcala_lo12
+# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo+4), kind: FK_NONE
-bl %plt(foo)
-# RELOC: R_LARCH_B26
-# INSTR: bl %plt(foo)
-# FIXUP: fixup A - offset: 0, value: %plt(foo), kind: fixup_loongarch_b26
+lu32i.d $t1, %pc64_lo20(foo)
+# RELOC: R_LARCH_PCALA64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %pc64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %pc64_lo20(foo), kind: FK_NONE
-bl foo
-# RELOC: R_LARCH_B26
-# INSTR: bl foo
-# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_loongarch_b26
+lu52i.d $t1, $t1, %pc64_hi12(foo)
+# RELOC: R_LARCH_PCALA64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %pc64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %pc64_hi12(foo), kind: FK_NONE
+
+pcalau12i $t1, %got_pc_hi20(foo)
+# RELOC: R_LARCH_GOT_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %got_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %got_pc_hi20(foo), kind: FK_NONE
+
+ld.d $t1, $a2, %got_pc_lo12(foo)
+# RELOC: R_LARCH_GOT_PC_LO12 foo 0x0
+# INSTR: ld.d $t1, $a2, %got_pc_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %got_pc_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %got64_pc_lo20(foo)
+# RELOC: R_LARCH_GOT64_PC_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %got64_pc_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %got64_pc_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %got64_pc_hi12(foo)
+# RELOC: R_LARCH_GOT64_PC_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %got64_pc_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %got64_pc_hi12(foo), kind: FK_NONE
+
+lu12i.w $t1, %got_hi20(foo)
+# RELOC: R_LARCH_GOT_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %got_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %got_hi20(foo), kind: FK_NONE
+
+ori $t1, $a2, %got_lo12(foo)
+# RELOC: R_LARCH_GOT_LO12 foo 0x0
+# INSTR: ori $t1, $a2, %got_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %got_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %got64_lo20(foo)
+# RELOC: R_LARCH_GOT64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %got64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %got64_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %got64_hi12(foo)
+# RELOC: R_LARCH_GOT64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %got64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %got64_hi12(foo), kind: FK_NONE
+
+lu12i.w $t1, %le_hi20(foo)
+# RELOC: R_LARCH_TLS_LE_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %le_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %le_hi20(foo), kind: fixup_loongarch_tls_le_hi20
+
+ori $t1, $a2, %le_lo12(foo)
+# RELOC: R_LARCH_TLS_LE_LO12 foo 0x0
+# INSTR: ori $t1, $a2, %le_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %le_lo12(foo), kind: fixup_loongarch_tls_le_lo12
+
+lu32i.d $t1, %le64_lo20(foo)
+# RELOC: R_LARCH_TLS_LE64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %le64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %le64_lo20(foo), kind: fixup_loongarch_tls_le64_lo20
+
+lu52i.d $t1, $t1, %le64_hi12(foo)
+# RELOC: R_LARCH_TLS_LE64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %le64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %le64_hi12(foo), kind: fixup_loongarch_tls_le64_hi12
+
+pcalau12i $t1, %ie_pc_hi20(foo)
+# RELOC: R_LARCH_TLS_IE_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %ie_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %ie_pc_hi20(foo), kind: FK_NONE
+
+ld.d $t1, $a2, %ie_pc_lo12(foo)
+# RELOC: R_LARCH_TLS_IE_PC_LO12 foo 0x0
+# INSTR: ld.d $t1, $a2, %ie_pc_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %ie_pc_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %ie64_pc_lo20(foo)
+# RELOC: R_LARCH_TLS_IE64_PC_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %ie64_pc_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %ie64_pc_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %ie64_pc_hi12(foo)
+# RELOC: R_LARCH_TLS_IE64_PC_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %ie64_pc_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %ie64_pc_hi12(foo), kind: FK_NONE
+
+lu12i.w $t1, %ie_hi20(foo)
+# RELOC: R_LARCH_TLS_IE_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %ie_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %ie_hi20(foo), kind: FK_NONE
+
+ori $t1, $a2, %ie_lo12(foo)
+# RELOC: R_LARCH_TLS_IE_LO12 foo 0x0
+# INSTR: ori $t1, $a2, %ie_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %ie_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %ie64_lo20(foo)
+# RELOC: R_LARCH_TLS_IE64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %ie64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %ie64_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %ie64_hi12(foo)
+# RELOC: R_LARCH_TLS_IE64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %ie64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %ie64_hi12(foo), kind: FK_NONE
+
+pcalau12i $t1, %ld_pc_hi20(foo)
+# RELOC: R_LARCH_TLS_LD_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %ld_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %ld_pc_hi20(foo), kind: FK_NONE
+
+lu12i.w $t1, %ld_hi20(foo)
+# RELOC: R_LARCH_TLS_LD_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %ld_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %ld_hi20(foo), kind: FK_NONE
+
+pcalau12i $t1, %gd_pc_hi20(foo)
+# RELOC: R_LARCH_TLS_GD_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %gd_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %gd_pc_hi20(foo), kind: FK_NONE
+
+lu12i.w $t1, %gd_hi20(foo)
+# RELOC: R_LARCH_TLS_GD_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %gd_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %gd_hi20(foo), kind: FK_NONE