From: Matheus Almeida Date: Thu, 5 Dec 2013 11:06:22 +0000 (+0000) Subject: [mips][msa] Fix issue with immediate fields of LD/ST instructions X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=4faa2b38fb0fa98fd3f157a5456c828c4e762dce;p=oota-llvm.git [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@196494 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 60508a8c4fc..c574f549a18 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -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; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 66428bdfa74..669e48a78b3 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -107,6 +107,9 @@ public: unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, SmallVectorImpl &Fixups) const; + unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const; + unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &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 &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 diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index ca4163d4e58..76f604d6603 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -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. diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index cc76f7edbc6..307e0fb8cc1 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -302,8 +302,7 @@ def InvertedImOperand : Operand { let ParserMatchClass = MipsInvertedImmoperand; } -// Address operand -def mem : Operand { +class mem_generic : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops ptr_rc, simm16); let EncoderMethod = "getMemEncoding"; @@ -311,6 +310,14 @@ def mem : Operand { 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 { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops ptr_rc, simm16); diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td index 9089be2abcb..7a588f6e950 100644 --- a/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/lib/Target/Mips/MipsMSAInstrInfo.td @@ -2269,7 +2269,7 @@ class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", int_mips_insve_d, class LD_DESC_BASE { 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 { dag OutOperandList = (outs); dag InOperandList = (ins ROWD:$wd, MemOpnd:$addr); diff --git a/test/MC/Mips/msa/test_mi10.s b/test/MC/Mips/msa/test_mi10.s index 80257cda851..94711ebaa7f 100644 --- a/test/MC/Mips/msa/test_mi10.s +++ b/test/MC/Mips/msa/test_mi10.s @@ -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] - -# 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) - - 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.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] + +# 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] + +# 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)