diff options
author | Matheus Almeida <matheus.almeida@imgtec.com> | 2013-12-05 11:06:22 +0000 |
---|---|---|
committer | Matheus Almeida <matheus.almeida@imgtec.com> | 2013-12-05 11:06:22 +0000 |
commit | 4faa2b38fb0fa98fd3f157a5456c828c4e762dce (patch) | |
tree | 34e88312dc314abf0ad04af96a779388192bd6f1 /lib/Target | |
parent | 52123d184232683deee6b51ab2245b186829f408 (diff) | |
download | llvm-4faa2b38fb0fa98fd3f157a5456c828c4e762dce.tar.gz llvm-4faa2b38fb0fa98fd3f157a5456c828c4e762dce.tar.bz2 llvm-4faa2b38fb0fa98fd3f157a5456c828c4e762dce.tar.xz |
[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
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 32 | ||||
-rw-r--r-- | lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 46 | ||||
-rw-r--r-- | lib/Target/Mips/MipsCodeEmitter.cpp | 7 | ||||
-rw-r--r-- | lib/Target/Mips/MipsInstrInfo.td | 11 | ||||
-rw-r--r-- | lib/Target/Mips/MipsMSAInstrInfo.td | 4 |
5 files changed, 95 insertions, 5 deletions
diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 60508a8c4f..c574f549a1 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 66428bdfa7..669e48a78b 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<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 diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index ca4163d4e5..76f604d660 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 cc76f7edbc..307e0fb8cc 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -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); diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td index 9089be2abc..7a588f6e95 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<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); |