forked from OSchip/llvm-project
[mips][msa] Fix issue with immediate fields of LD/ST instructions
not being correctly encoded/decoded. In more detail, immediate fields of LD/ST instructions should be divided/multiplied by the size of the data format before encoding and after decoding, respectively. llvm-svn: 196494
This commit is contained in:
parent
e4def5e228
commit
6b59c449d9
|
@ -565,7 +565,37 @@ static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn,
|
|||
|
||||
Inst.addOperand(MCOperand::CreateReg(Reg));
|
||||
Inst.addOperand(MCOperand::CreateReg(Base));
|
||||
Inst.addOperand(MCOperand::CreateImm(Offset));
|
||||
|
||||
// The immediate field of an LD/ST instruction is scaled which means it must
|
||||
// be multiplied (when decoding) by the size (in bytes) of the instructions'
|
||||
// data format.
|
||||
// .b - 1 byte
|
||||
// .h - 2 bytes
|
||||
// .w - 4 bytes
|
||||
// .d - 8 bytes
|
||||
switch(Inst.getOpcode())
|
||||
{
|
||||
default:
|
||||
assert (0 && "Unexpected instruction");
|
||||
return MCDisassembler::Fail;
|
||||
break;
|
||||
case Mips::LD_B:
|
||||
case Mips::ST_B:
|
||||
Inst.addOperand(MCOperand::CreateImm(Offset));
|
||||
break;
|
||||
case Mips::LD_H:
|
||||
case Mips::ST_H:
|
||||
Inst.addOperand(MCOperand::CreateImm(Offset << 1));
|
||||
break;
|
||||
case Mips::LD_W:
|
||||
case Mips::ST_W:
|
||||
Inst.addOperand(MCOperand::CreateImm(Offset << 2));
|
||||
break;
|
||||
case Mips::LD_D:
|
||||
case Mips::ST_D:
|
||||
Inst.addOperand(MCOperand::CreateImm(Offset << 3));
|
||||
break;
|
||||
}
|
||||
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
|
|
@ -107,6 +107,9 @@ public:
|
|||
unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
|
||||
|
@ -480,6 +483,49 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
|||
return getExprOpValue(MO.getExpr(),Fixups);
|
||||
}
|
||||
|
||||
/// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST
|
||||
/// instructions.
|
||||
unsigned
|
||||
MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
// Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
|
||||
assert(MI.getOperand(OpNo).isReg());
|
||||
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
|
||||
unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
|
||||
|
||||
// The immediate field of an LD/ST instruction is scaled which means it must
|
||||
// be divided (when encoding) by the size (in bytes) of the instructions'
|
||||
// data format.
|
||||
// .b - 1 byte
|
||||
// .h - 2 bytes
|
||||
// .w - 4 bytes
|
||||
// .d - 8 bytes
|
||||
switch(MI.getOpcode())
|
||||
{
|
||||
default:
|
||||
assert (0 && "Unexpected instruction");
|
||||
break;
|
||||
case Mips::LD_B:
|
||||
case Mips::ST_B:
|
||||
// We don't need to scale the offset in this case
|
||||
break;
|
||||
case Mips::LD_H:
|
||||
case Mips::ST_H:
|
||||
OffBits >>= 1;
|
||||
break;
|
||||
case Mips::LD_W:
|
||||
case Mips::ST_W:
|
||||
OffBits >>= 2;
|
||||
break;
|
||||
case Mips::LD_D:
|
||||
case Mips::ST_D:
|
||||
OffBits >>= 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return (OffBits & 0xFFFF) | RegBits;
|
||||
}
|
||||
|
||||
/// getMemEncoding - Return binary encoding of memory related operand.
|
||||
/// If the offset operand requires relocation, record the relocation.
|
||||
unsigned
|
||||
|
|
|
@ -112,6 +112,7 @@ private:
|
|||
unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getMSAMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||
unsigned getLSAImmEncoding(const MachineInstr &MI, unsigned OpNo) const;
|
||||
|
@ -224,6 +225,12 @@ unsigned MipsCodeEmitter::getMemEncodingMMImm12(const MachineInstr &MI,
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned MipsCodeEmitter::getMSAMemEncoding(const MachineInstr &MI,
|
||||
unsigned OpNo) const {
|
||||
llvm_unreachable("Unimplemented function.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned MipsCodeEmitter::getSizeExtEncoding(const MachineInstr &MI,
|
||||
unsigned OpNo) const {
|
||||
// size is encoded as size-1.
|
||||
|
|
|
@ -302,8 +302,7 @@ def InvertedImOperand : Operand<i32> {
|
|||
let ParserMatchClass = MipsInvertedImmoperand;
|
||||
}
|
||||
|
||||
// Address operand
|
||||
def mem : Operand<iPTR> {
|
||||
class mem_generic : Operand<iPTR> {
|
||||
let PrintMethod = "printMemOperand";
|
||||
let MIOperandInfo = (ops ptr_rc, simm16);
|
||||
let EncoderMethod = "getMemEncoding";
|
||||
|
@ -311,6 +310,14 @@ def mem : Operand<iPTR> {
|
|||
let OperandType = "OPERAND_MEMORY";
|
||||
}
|
||||
|
||||
// Address operand
|
||||
def mem : mem_generic;
|
||||
|
||||
// MSA specific address operand
|
||||
def mem_msa : mem_generic {
|
||||
let EncoderMethod = "getMSAMemEncoding";
|
||||
}
|
||||
|
||||
def mem_ea : Operand<iPTR> {
|
||||
let PrintMethod = "printMemOperandEA";
|
||||
let MIOperandInfo = (ops ptr_rc, simm16);
|
||||
|
|
|
@ -2269,7 +2269,7 @@ class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", int_mips_insve_d,
|
|||
|
||||
class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||
ValueType TyNode, RegisterOperand ROWD,
|
||||
Operand MemOpnd = mem, ComplexPattern Addr = addrRegImm,
|
||||
Operand MemOpnd = mem_msa, ComplexPattern Addr = addrRegImm,
|
||||
InstrItinClass itin = NoItinerary> {
|
||||
dag OutOperandList = (outs ROWD:$wd);
|
||||
dag InOperandList = (ins MemOpnd:$addr);
|
||||
|
@ -2590,7 +2590,7 @@ class SRLRI_D_DESC : MSA_BIT_D_X_DESC_BASE<"srlri.d", int_mips_srlri_d,
|
|||
|
||||
class ST_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||
ValueType TyNode, RegisterOperand ROWD,
|
||||
Operand MemOpnd = mem, ComplexPattern Addr = addrRegImm,
|
||||
Operand MemOpnd = mem_msa, ComplexPattern Addr = addrRegImm,
|
||||
InstrItinClass itin = NoItinerary> {
|
||||
dag OutOperandList = (outs);
|
||||
dag InOperandList = (ins ROWD:$wd, MemOpnd:$addr);
|
||||
|
|
|
@ -2,29 +2,83 @@
|
|||
#
|
||||
# RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -mattr=+msa -arch=mips -filetype=obj -o - | llvm-objdump -d -triple=mipsel-unknown-linux -mattr=+msa -arch=mips - | FileCheck %s -check-prefix=CHECKOBJDUMP
|
||||
#
|
||||
# CHECK: ld.b $w2, 1($7) # encoding: [0x78,0x01,0x38,0xa0]
|
||||
# CHECK: ld.h $w16, -9($zero) # encoding: [0x7b,0xf7,0x04,0x21]
|
||||
# CHECK: ld.w $w13, -6($4) # encoding: [0x7b,0xfa,0x23,0x62]
|
||||
# CHECK: ld.d $w1, -5($16) # encoding: [0x7b,0xfb,0x80,0x63]
|
||||
# CHECK: st.b $w29, 1($14) # encoding: [0x78,0x01,0x77,0x64]
|
||||
# CHECK: st.h $w6, -1($8) # encoding: [0x7b,0xff,0x41,0xa5]
|
||||
# CHECK: st.w $w18, 8($15) # encoding: [0x78,0x08,0x7c,0xa6]
|
||||
# CHECK: st.d $w3, -14($18) # encoding: [0x7b,0xf2,0x90,0xe7]
|
||||
# CHECK: ld.b $w0, -512($1) # encoding: [0x7a,0x00,0x08,0x20]
|
||||
# CHECK: ld.b $w1, 0($2) # encoding: [0x78,0x00,0x10,0x60]
|
||||
# CHECK: ld.b $w2, 511($3) # encoding: [0x79,0xff,0x18,0xa0]
|
||||
|
||||
# CHECKOBJDUMP: ld.b $w2, 1($7)
|
||||
# CHECKOBJDUMP: ld.h $w16, -9($zero)
|
||||
# CHECKOBJDUMP: ld.w $w13, -6($4)
|
||||
# CHECKOBJDUMP: ld.d $w1, -5($16)
|
||||
# CHECKOBJDUMP: st.b $w29, 1($14)
|
||||
# CHECKOBJDUMP: st.h $w6, -1($8)
|
||||
# CHECKOBJDUMP: st.w $w18, 8($15)
|
||||
# CHECKOBJDUMP: st.d $w3, -14($18)
|
||||
# CHECK: ld.h $w3, -1024($4) # encoding: [0x7a,0x00,0x20,0xe1]
|
||||
# CHECK: ld.h $w4, -512($5) # encoding: [0x7b,0x00,0x29,0x21]
|
||||
# CHECK: ld.h $w5, 0($6) # encoding: [0x78,0x00,0x31,0x61]
|
||||
# CHECK: ld.h $w6, 512($7) # encoding: [0x79,0x00,0x39,0xa1]
|
||||
# CHECK: ld.h $w7, 1022($8) # encoding: [0x79,0xff,0x41,0xe1]
|
||||
|
||||
ld.b $w2, 1($7)
|
||||
ld.h $w16, -9($zero)
|
||||
ld.w $w13, -6($4)
|
||||
ld.d $w1, -5($16)
|
||||
st.b $w29, 1($14)
|
||||
st.h $w6, -1($8)
|
||||
st.w $w18, 8($15)
|
||||
st.d $w3, -14($18)
|
||||
# CHECK: ld.w $w8, -2048($9) # encoding: [0x7a,0x00,0x4a,0x22]
|
||||
# CHECK: ld.w $w9, -1024($10) # encoding: [0x7b,0x00,0x52,0x62]
|
||||
# CHECK: ld.w $w10, -512($11) # encoding: [0x7b,0x80,0x5a,0xa2]
|
||||
# CHECK: ld.w $w11, 512($12) # encoding: [0x78,0x80,0x62,0xe2]
|
||||
# CHECK: ld.w $w12, 1024($13) # encoding: [0x79,0x00,0x6b,0x22]
|
||||
# CHECK: ld.w $w13, 2044($14) # encoding: [0x79,0xff,0x73,0x62]
|
||||
|
||||
# CHECK: ld.d $w14, -4096($15) # encoding: [0x7a,0x00,0x7b,0xa3]
|
||||
# CHECK: ld.d $w15, -2048($16) # encoding: [0x7b,0x00,0x83,0xe3]
|
||||
# CHECK: ld.d $w16, -1024($17) # encoding: [0x7b,0x80,0x8c,0x23]
|
||||
# CHECK: ld.d $w17, -512($18) # encoding: [0x7b,0xc0,0x94,0x63]
|
||||
# CHECK: ld.d $w18, 0($19) # encoding: [0x78,0x00,0x9c,0xa3]
|
||||
# CHECK: ld.d $w19, 512($20) # encoding: [0x78,0x40,0xa4,0xe3]
|
||||
# CHECK: ld.d $w20, 1024($21) # encoding: [0x78,0x80,0xad,0x23]
|
||||
# CHECK: ld.d $w21, 2048($22) # encoding: [0x79,0x00,0xb5,0x63]
|
||||
# CHECK: ld.d $w22, 4088($23) # encoding: [0x79,0xff,0xbd,0xa3]
|
||||
|
||||
# CHECKOBJDUMP: ld.b $w0, -512($1)
|
||||
# CHECKOBJDUMP: ld.b $w1, 0($2)
|
||||
# CHECKOBJDUMP: ld.b $w2, 511($3)
|
||||
|
||||
# CHECKOBJDUMP: ld.h $w3, -1024($4)
|
||||
# CHECKOBJDUMP: ld.h $w4, -512($5)
|
||||
# CHECKOBJDUMP: ld.h $w5, 0($6)
|
||||
# CHECKOBJDUMP: ld.h $w6, 512($7)
|
||||
# CHECKOBJDUMP: ld.h $w7, 1022($8)
|
||||
|
||||
# CHECKOBJDUMP: ld.w $w8, -2048($9)
|
||||
# CHECKOBJDUMP: ld.w $w9, -1024($10)
|
||||
# CHECKOBJDUMP: ld.w $w10, -512($11)
|
||||
# CHECKOBJDUMP: ld.w $w11, 512($12)
|
||||
# CHECKOBJDUMP: ld.w $w12, 1024($13)
|
||||
# CHECKOBJDUMP: ld.w $w13, 2044($14)
|
||||
|
||||
# CHECKOBJDUMP: ld.d $w14, -4096($15)
|
||||
# CHECKOBJDUMP: ld.d $w15, -2048($16)
|
||||
# CHECKOBJDUMP: ld.d $w16, -1024($17)
|
||||
# CHECKOBJDUMP: ld.d $w17, -512($18)
|
||||
# CHECKOBJDUMP: ld.d $w18, 0($19)
|
||||
# CHECKOBJDUMP: ld.d $w19, 512($20)
|
||||
# CHECKOBJDUMP: ld.d $w20, 1024($21)
|
||||
# CHECKOBJDUMP: ld.d $w21, 2048($22)
|
||||
# CHECKOBJDUMP: ld.d $w22, 4088($23)
|
||||
|
||||
ld.b $w0, -512($1)
|
||||
ld.b $w1, 0($2)
|
||||
ld.b $w2, 511($3)
|
||||
|
||||
ld.h $w3, -1024($4)
|
||||
ld.h $w4, -512($5)
|
||||
ld.h $w5, 0($6)
|
||||
ld.h $w6, 512($7)
|
||||
ld.h $w7, 1022($8)
|
||||
|
||||
ld.w $w8, -2048($9)
|
||||
ld.w $w9, -1024($10)
|
||||
ld.w $w10, -512($11)
|
||||
ld.w $w11, 512($12)
|
||||
ld.w $w12, 1024($13)
|
||||
ld.w $w13, 2044($14)
|
||||
|
||||
ld.d $w14, -4096($15)
|
||||
ld.d $w15, -2048($16)
|
||||
ld.d $w16, -1024($17)
|
||||
ld.d $w17, -512($18)
|
||||
ld.d $w18, 0($19)
|
||||
ld.d $w19, 512($20)
|
||||
ld.d $w20, 1024($21)
|
||||
ld.d $w21, 2048($22)
|
||||
ld.d $w22, 4088($23)
|
||||
|
|
Loading…
Reference in New Issue