From: Simon Atanasyan Date: Wed, 7 Aug 2019 12:21:26 +0000 (+0000) Subject: [Mips] Instruction `sc` now accepts symbol as an argument X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=de0cf9041ae9ced931db86e2dec756e2294a888c;p=llvm [Mips] Instruction `sc` now accepts symbol as an argument Function MipsAsmParser::expandMemInst() did not properly handle instruction `sc` with a symbol as an argument because first argument would be counted twice. We add additional checks and handle this case separately. Patch by Mirko Brkusanin. Differential Revision: https://reviews.llvm.org/D64252 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368160 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index aee434cb006..d7396b66048 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -3581,7 +3581,6 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, assert(DstRegOp.isReg() && "expected register operand kind"); const MCOperand &BaseRegOp = Inst.getOperand(1); assert(BaseRegOp.isReg() && "expected register operand kind"); - const MCOperand &OffsetOp = Inst.getOperand(2); MipsTargetStreamer &TOut = getTargetStreamer(); unsigned DstReg = DstRegOp.getReg(); @@ -3603,6 +3602,26 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return; } + if (Inst.getNumOperands() > 3) { + const MCOperand &BaseRegOp = Inst.getOperand(2); + assert(BaseRegOp.isReg() && "expected register operand kind"); + const MCOperand &ExprOp = Inst.getOperand(3); + assert(ExprOp.isExpr() && "expected expression oprand kind"); + + unsigned BaseReg = BaseRegOp.getReg(); + const MCExpr *ExprOffset = ExprOp.getExpr(); + + MCOperand LoOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); + MCOperand HiOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); + TOut.emitSCWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, + LoOperand, TmpReg, IDLoc, STI); + return; + } + + const MCOperand &OffsetOp = Inst.getOperand(2); + if (OffsetOp.isImm()) { int64_t LoOffset = OffsetOp.getImm() & 0xffff; int64_t HiOffset = OffsetOp.getImm() & ~0xffff; @@ -3628,35 +3647,39 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return; } - assert(OffsetOp.isExpr() && "expected expression operand kind"); - if (inPicMode()) { - // FIXME: - // a) Fix lw/sw $reg, symbol($reg) instruction expanding. - // b) If expression includes offset (sym + number), do not - // encode the offset into a relocation. Take it in account - // in the last load/store instruction. - // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations - // do not exceed 16-bit. - // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead - // of R_MIPS_GOT_DISP in appropriate cases to reduce number - // of GOT entries. - expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(), - IDLoc, Out, STI); - TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI); - } else { - const MCExpr *ExprOffset = OffsetOp.getExpr(); - MCOperand LoOperand = MCOperand::createExpr( - MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); - MCOperand HiOperand = MCOperand::createExpr( - MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); - - if (IsLoad) - TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, - LoOperand, TmpReg, IDLoc, STI); - else - TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, - LoOperand, TmpReg, IDLoc, STI); + if (OffsetOp.isExpr()) { + if (inPicMode()) { + // FIXME: + // a) Fix lw/sw $reg, symbol($reg) instruction expanding. + // b) If expression includes offset (sym + number), do not + // encode the offset into a relocation. Take it in account + // in the last load/store instruction. + // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations + // do not exceed 16-bit. + // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead + // of R_MIPS_GOT_DISP in appropriate cases to reduce number + // of GOT entries. + expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(), + IDLoc, Out, STI); + TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI); + } else { + const MCExpr *ExprOffset = OffsetOp.getExpr(); + MCOperand LoOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); + MCOperand HiOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); + + if (IsLoad) + TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, + LoOperand, TmpReg, IDLoc, STI); + else + TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, + HiOperand, LoOperand, TmpReg, IDLoc, STI); + } + return; } + + llvm_unreachable("unexpected operand type"); } bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index e3bdb3b140a..48dbd968958 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -216,6 +216,19 @@ void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI); } +void MipsTargetStreamer::emitRRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, + unsigned Reg2, MCOperand Op3, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + MCInst TmpInst; + TmpInst.setOpcode(Opcode); + TmpInst.addOperand(MCOperand::createReg(Reg0)); + TmpInst.addOperand(MCOperand::createReg(Reg1)); + TmpInst.addOperand(MCOperand::createReg(Reg2)); + TmpInst.addOperand(Op3); + TmpInst.setLoc(IDLoc); + getStreamer().EmitInstruction(TmpInst, *STI); +} + void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm, SMLoc IDLoc, const MCSubtargetInfo *STI) { @@ -328,6 +341,36 @@ void MipsTargetStreamer::emitStoreWithSymOffset( emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI); } +/// Emit a store instruction with an symbol offset. +void MipsTargetStreamer::emitSCWithSymOffset(unsigned Opcode, unsigned SrcReg, + unsigned BaseReg, + MCOperand &HiOperand, + MCOperand &LoOperand, + unsigned ATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + // sc $8, sym => lui $at, %hi(sym) + // sc $8, %lo(sym)($at) + + // Generate the base address in ATReg. + emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI); + if (!isMicroMips(STI) && isMipsR6(STI)) { + // For non-micromips r6 offset for 'sc' is not in the lower 16 bits so we + // put it in 'at'. + // sc $8, sym => lui $at, %hi(sym) + // addiu $at, $at, %lo(sym) + // sc $8, 0($at) + emitRRX(Mips::ADDiu, ATReg, ATReg, LoOperand, IDLoc, STI); + MCOperand Offset = MCOperand::createImm(0); + // Emit the store with the adjusted base and offset. + emitRRRX(Opcode, SrcReg, SrcReg, ATReg, Offset, IDLoc, STI); + } else { + if (BaseReg != Mips::ZERO) + emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI); + // Emit the store with the adjusted base and offset. + emitRRRX(Opcode, SrcReg, SrcReg, ATReg, LoOperand, IDLoc, STI); + } +} + /// Emit a load instruction with an immediate offset. DstReg and TmpReg are /// permitted to be the same register iff DstReg is distinct from BaseReg and /// DstReg is a GPR. It is the callers responsibility to identify such cases @@ -388,6 +431,15 @@ void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg, emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI); } +bool MipsTargetStreamer::isMipsR6(const MCSubtargetInfo *STI) const { + return STI->getFeatureBits()[Mips::FeatureMips32r6] || + STI->getFeatureBits()[Mips::FeatureMips64r6]; +} + +bool MipsTargetStreamer::isMicroMips(const MCSubtargetInfo *STI) const { + return STI->getFeatureBits()[Mips::FeatureMicroMips]; +} + MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS) : MipsTargetStreamer(S), OS(OS) {} diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h index 1fa8ebadd64..91f26b2e4cd 100644 --- a/lib/Target/Mips/MipsTargetStreamer.h +++ b/lib/Target/Mips/MipsTargetStreamer.h @@ -130,6 +130,8 @@ public: SMLoc IDLoc, const MCSubtargetInfo *STI); void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, SMLoc IDLoc, const MCSubtargetInfo *STI); + void emitRRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, + MCOperand Op3, SMLoc IDLoc, const MCSubtargetInfo *STI); void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm, SMLoc IDLoc, const MCSubtargetInfo *STI); void emitRRIII(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm0, @@ -158,6 +160,10 @@ public: unsigned BaseReg, MCOperand &HiOperand, MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc, const MCSubtargetInfo *STI); + void emitSCWithSymOffset(unsigned Opcode, unsigned SrcReg, unsigned BaseReg, + MCOperand &HiOperand, MCOperand &LoOperand, + unsigned ATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI); void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg, int64_t Offset, unsigned TmpReg, SMLoc IDLoc, const MCSubtargetInfo *STI); @@ -185,6 +191,9 @@ public: return *ABI; } + bool isMipsR6(const MCSubtargetInfo *STI) const; + bool isMicroMips(const MCSubtargetInfo *STI) const; + protected: llvm::Optional ABI; MipsABIFlagsSection ABIFlagsSection; diff --git a/test/MC/Mips/sym-sc.s b/test/MC/Mips/sym-sc.s new file mode 100644 index 00000000000..208c5d84ed6 --- /dev/null +++ b/test/MC/Mips/sym-sc.s @@ -0,0 +1,74 @@ +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips2 %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32 %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32r2 %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips3 %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips64 %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips64r2 %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPS +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32r6 %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPSR6 +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips64r6 %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefix=MIPSR6 +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32r2 -mattr=+micromips %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefixes=MICROMIPS,MICROMIPSR2 +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips32r6 -mattr=+micromips %s -o - \ +# RUN: | llvm-objdump -d -r - | FileCheck %s --check-prefixes=MICROMIPS,MICROMIPSR6 + +# MIPS: 0: e0 6c 00 00 sc $12, 0($3) +# MIPSR6: 0: 7c 6c 00 26 sc $12, 0($3) +# MICROMIPS: 0: 61 83 b0 00 sc $12, 0($3) +sc $12, 0($3) + +# MIPS: 4: e0 6c 00 04 sc $12, 4($3) +# MIPSR6: 4: 7c 6c 02 26 sc $12, 4($3) +# MICROMIPS: 4: 61 83 b0 04 sc $12, 4($3) +sc $12, 4($3) + +# MIPS: 8: 3c 01 00 00 lui $1, 0 +# MIPS: 00000008: R_MIPS_HI16 symbol +# MIPS: c: e0 2c 00 00 sc $12, 0($1) +# MIPS: 0000000c: R_MIPS_LO16 symbol + +# MIPSR6: 8: 3c 01 00 00 aui $1, $zero, 0 +# MIPSR6: 00000008: R_MIPS_HI16 symbol +# MIPSR6: c: 24 21 00 00 addiu $1, $1, 0 +# MIPSR6: 0000000c: R_MIPS_LO16 symbol +# MIPSR6: 10: 7c 2c 00 26 sc $12, 0($1) + +# MICROMIPSR2: 8: 41 a1 00 00 lui $1, 0 +# MICROMIPSR2: 00000008: R_MICROMIPS_HI16 symbol +# MICROMIPSR2: c: 61 81 b0 00 sc $12, 0($1) +# MICROMIPSR2: 0000000c: R_MICROMIPS_LO16 symbol + +# MICROMIPSR6: 8: 3c 01 00 00 lh $zero, 0($1) +# MICROMIPSR6: 00000008: R_MICROMIPS_HI16 symbol +# MICROMIPSR6: c: 61 81 b0 00 sc $12, 0($1) +# MICROMIPSR6: 0000000c: R_MICROMIPS_LO16 symbol +sc $12, symbol + +# MIPS: 10: 3c 01 00 00 lui $1, 0 +# MIPS: 00000010: R_MIPS_HI16 symbol +# MIPS: 14: e0 2c 00 08 sc $12, 8($1) +# MIPS: 00000014: R_MIPS_LO16 symbol + +# MIPSR6: 14: 3c 01 00 00 aui $1, $zero, 0 +# MIPSR6: 00000014: R_MIPS_HI16 symbol +# MIPSR6: 18: 24 21 00 08 addiu $1, $1, 8 +# MIPSR6: 00000018: R_MIPS_LO16 symbol +# MIPSR6: 1c: 7c 2c 00 26 sc $12, 0($1) + +# MICROMIPSR2: 10: 41 a1 00 00 lui $1, 0 +# MICROMIPSR2: 00000010: R_MICROMIPS_HI16 symbol +# MICROMIPSR2: 14: 61 81 b0 08 sc $12, 8($1) +# MICROMIPSR2: 00000014: R_MICROMIPS_LO16 symbol + +# MICROMIPSR6: 10: 3c 01 00 00 lh $zero, 0($1) +# MICROMIPSR6: 00000010: R_MICROMIPS_HI16 symbol +# MICROMIPSR6: 14: 61 81 b0 08 sc $12, 8($1) +# MICROMIPSR6: 00000014: R_MICROMIPS_LO16 symbol +sc $12, symbol + 8