1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[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

llvm-svn: 368160
This commit is contained in:
Simon Atanasyan 2019-08-07 12:21:26 +00:00
parent a94842ace2
commit 9a3474505e
4 changed files with 186 additions and 28 deletions

View File

@ -3581,7 +3581,6 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
assert(DstRegOp.isReg() && "expected register operand kind"); assert(DstRegOp.isReg() && "expected register operand kind");
const MCOperand &BaseRegOp = Inst.getOperand(1); const MCOperand &BaseRegOp = Inst.getOperand(1);
assert(BaseRegOp.isReg() && "expected register operand kind"); assert(BaseRegOp.isReg() && "expected register operand kind");
const MCOperand &OffsetOp = Inst.getOperand(2);
MipsTargetStreamer &TOut = getTargetStreamer(); MipsTargetStreamer &TOut = getTargetStreamer();
unsigned DstReg = DstRegOp.getReg(); unsigned DstReg = DstRegOp.getReg();
@ -3603,6 +3602,26 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return; 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()) { if (OffsetOp.isImm()) {
int64_t LoOffset = OffsetOp.getImm() & 0xffff; int64_t LoOffset = OffsetOp.getImm() & 0xffff;
int64_t HiOffset = OffsetOp.getImm() & ~0xffff; int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
@ -3628,35 +3647,39 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return; return;
} }
assert(OffsetOp.isExpr() && "expected expression operand kind"); if (OffsetOp.isExpr()) {
if (inPicMode()) { if (inPicMode()) {
// FIXME: // FIXME:
// a) Fix lw/sw $reg, symbol($reg) instruction expanding. // a) Fix lw/sw $reg, symbol($reg) instruction expanding.
// b) If expression includes offset (sym + number), do not // b) If expression includes offset (sym + number), do not
// encode the offset into a relocation. Take it in account // encode the offset into a relocation. Take it in account
// in the last load/store instruction. // in the last load/store instruction.
// c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations
// do not exceed 16-bit. // do not exceed 16-bit.
// d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
// of R_MIPS_GOT_DISP in appropriate cases to reduce number // of R_MIPS_GOT_DISP in appropriate cases to reduce number
// of GOT entries. // of GOT entries.
expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(), expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(),
IDLoc, Out, STI); IDLoc, Out, STI);
TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI); TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI);
} else { } else {
const MCExpr *ExprOffset = OffsetOp.getExpr(); const MCExpr *ExprOffset = OffsetOp.getExpr();
MCOperand LoOperand = MCOperand::createExpr( MCOperand LoOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
MCOperand HiOperand = MCOperand::createExpr( MCOperand HiOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
if (IsLoad) if (IsLoad)
TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
LoOperand, TmpReg, IDLoc, STI); LoOperand, TmpReg, IDLoc, STI);
else else
TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg,
LoOperand, TmpReg, IDLoc, STI); HiOperand, LoOperand, TmpReg, IDLoc, STI);
}
return;
} }
llvm_unreachable("unexpected operand type");
} }
bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,

View File

@ -216,6 +216,19 @@ void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI); 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, void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
int16_t Imm, SMLoc IDLoc, int16_t Imm, SMLoc IDLoc,
const MCSubtargetInfo *STI) { const MCSubtargetInfo *STI) {
@ -328,6 +341,36 @@ void MipsTargetStreamer::emitStoreWithSymOffset(
emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI); 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 /// 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 /// 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 /// 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); 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, MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
formatted_raw_ostream &OS) formatted_raw_ostream &OS)
: MipsTargetStreamer(S), OS(OS) {} : MipsTargetStreamer(S), OS(OS) {}

View File

@ -130,6 +130,8 @@ public:
SMLoc IDLoc, const MCSubtargetInfo *STI); SMLoc IDLoc, const MCSubtargetInfo *STI);
void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
SMLoc IDLoc, const MCSubtargetInfo *STI); 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, void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
SMLoc IDLoc, const MCSubtargetInfo *STI); SMLoc IDLoc, const MCSubtargetInfo *STI);
void emitRRIII(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm0, void emitRRIII(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm0,
@ -158,6 +160,10 @@ public:
unsigned BaseReg, MCOperand &HiOperand, unsigned BaseReg, MCOperand &HiOperand,
MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc, MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
const MCSubtargetInfo *STI); 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, void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg,
int64_t Offset, unsigned TmpReg, SMLoc IDLoc, int64_t Offset, unsigned TmpReg, SMLoc IDLoc,
const MCSubtargetInfo *STI); const MCSubtargetInfo *STI);
@ -185,6 +191,9 @@ public:
return *ABI; return *ABI;
} }
bool isMipsR6(const MCSubtargetInfo *STI) const;
bool isMicroMips(const MCSubtargetInfo *STI) const;
protected: protected:
llvm::Optional<MipsABIInfo> ABI; llvm::Optional<MipsABIInfo> ABI;
MipsABIFlagsSection ABIFlagsSection; MipsABIFlagsSection ABIFlagsSection;

74
test/MC/Mips/sym-sc.s Normal file
View File

@ -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