mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 19:12:56 +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:
parent
a94842ace2
commit
9a3474505e
@ -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,
|
||||||
|
@ -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) {}
|
||||||
|
@ -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
74
test/MC/Mips/sym-sc.s
Normal 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
|
Loading…
Reference in New Issue
Block a user