diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp --- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp @@ -170,29 +170,90 @@ 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 { @@ -202,29 +263,90 @@ 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. @@ -687,15 +809,30 @@ 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, @@ -706,10 +843,23 @@ 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), @@ -719,7 +869,8 @@ 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, diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -110,10 +110,19 @@ let ParserMatchClass = UImmAsmOperand<8>; } -def uimm12 : Operand, ImmLeaf(Imm);}]> { +class UImm12Operand : Operand, + ImmLeaf (Imm);}]> { + let DecoderMethod = "decodeUImmOperand<12>"; +} + +def uimm12 : UImm12Operand { let ParserMatchClass = UImmAsmOperand<12>; } +def uimm12_ori : UImm12Operand { + let ParserMatchClass = UImmAsmOperand<12, "ori">; +} + def uimm14 : Operand { let ParserMatchClass = UImmAsmOperand<14>; } @@ -122,11 +131,23 @@ let ParserMatchClass = UImmAsmOperand<15>; } -def simm12 : Operand, ImmLeaf(Imm);}]> { - let ParserMatchClass = SImmAsmOperand<12>; +class SImm12Operand : Operand, + ImmLeaf (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, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<14, "lsl2">; @@ -164,6 +185,14 @@ 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 { let ParserMatchClass = SImmAsmOperand<21, "lsl2">; let EncoderMethod = "getImmOpValueAsr2"; @@ -282,7 +311,7 @@ class LOAD_3R op, string opstr> : Fmt3R; class LOAD_2RI12 op, string opstr> - : Fmt2RI12; class LOAD_2RI14 op, string opstr> : Fmt2RI14; class STORE_2RI12 op, string opstr> - : Fmt2RI12; class STORE_2RI14 op, string opstr> : Fmt2RI14; 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>; @@ -345,7 +374,7 @@ 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">; @@ -441,16 +470,16 @@ // 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">; diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp --- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp @@ -42,10 +42,10 @@ 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. } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -45,9 +45,17 @@ // 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. }; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp @@ -67,12 +67,28 @@ 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. } } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h @@ -9,6 +9,7 @@ #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 @@ -21,17 +22,91 @@ // 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 diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp @@ -135,16 +135,134 @@ 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(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; } } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h @@ -23,12 +23,44 @@ 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. }; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp @@ -65,18 +65,117 @@ 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(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); } diff --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s --- a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s +++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s @@ -1,7 +1,9 @@ ## 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 @@ -37,20 +39,24 @@ ## 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 @@ -80,41 +86,43 @@ ## 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 diff --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s --- a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s +++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s @@ -29,11 +29,9 @@ 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 @@ -41,6 +39,10 @@ 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] @@ -62,11 +64,13 @@ # 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 diff --git a/llvm/test/MC/LoongArch/Relocations/relocations.s b/llvm/test/MC/LoongArch/Relocations/relocations.s --- a/llvm/test/MC/LoongArch/Relocations/relocations.s +++ b/llvm/test/MC/LoongArch/Relocations/relocations.s @@ -14,42 +14,202 @@ .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